Ionite
8 months ago
committed by
GitHub
61 changed files with 2926 additions and 648 deletions
@ -1,7 +1,10 @@
|
||||
namespace StabilityMatrix.Avalonia.Models; |
||||
using System.Collections.ObjectModel; |
||||
|
||||
namespace StabilityMatrix.Avalonia.Models; |
||||
|
||||
public class PackageOutputCategory |
||||
{ |
||||
public ObservableCollection<PackageOutputCategory> SubDirectories { get; set; } = new(); |
||||
public required string Name { get; set; } |
||||
public required string Path { get; set; } |
||||
} |
||||
|
@ -0,0 +1,148 @@
|
||||
using System; |
||||
using System.Collections.Immutable; |
||||
using System.Linq; |
||||
using System.Threading.Tasks; |
||||
using Avalonia.Controls.Notifications; |
||||
using CommunityToolkit.Mvvm.ComponentModel; |
||||
using Microsoft.Extensions.Logging; |
||||
using StabilityMatrix.Avalonia.Models; |
||||
using StabilityMatrix.Avalonia.ViewModels; |
||||
using StabilityMatrix.Core.Attributes; |
||||
using StabilityMatrix.Core.Extensions; |
||||
using StabilityMatrix.Core.Helper.Factory; |
||||
using StabilityMatrix.Core.Models; |
||||
using StabilityMatrix.Core.Models.FileInterfaces; |
||||
using StabilityMatrix.Core.Models.Packages; |
||||
using StabilityMatrix.Core.Python; |
||||
using StabilityMatrix.Core.Services; |
||||
|
||||
namespace StabilityMatrix.Avalonia.Services; |
||||
|
||||
[Singleton] |
||||
public partial class RunningPackageService( |
||||
ILogger<RunningPackageService> logger, |
||||
IPackageFactory packageFactory, |
||||
INotificationService notificationService, |
||||
ISettingsManager settingsManager, |
||||
IPyRunner pyRunner |
||||
) : ObservableObject |
||||
{ |
||||
// 🤔 what if we put the ConsoleViewModel inside the BasePackage? 🤔 |
||||
[ObservableProperty] |
||||
private ObservableDictionary<Guid, RunningPackageViewModel> runningPackages = []; |
||||
|
||||
public async Task<PackagePair?> StartPackage(InstalledPackage installedPackage, string? command = null) |
||||
{ |
||||
var activeInstallName = installedPackage.PackageName; |
||||
var basePackage = string.IsNullOrWhiteSpace(activeInstallName) |
||||
? null |
||||
: packageFactory.GetNewBasePackage(installedPackage); |
||||
|
||||
if (basePackage == null) |
||||
{ |
||||
logger.LogWarning( |
||||
"During launch, package name '{PackageName}' did not match a definition", |
||||
activeInstallName |
||||
); |
||||
|
||||
notificationService.Show( |
||||
new Notification( |
||||
"Package name invalid", |
||||
"Install package name did not match a definition. Please reinstall and let us know about this issue.", |
||||
NotificationType.Error |
||||
) |
||||
); |
||||
return null; |
||||
} |
||||
|
||||
// If this is the first launch (LaunchArgs is null), |
||||
// load and save a launch options dialog vm |
||||
// so that dynamic initial values are saved. |
||||
if (installedPackage.LaunchArgs == null) |
||||
{ |
||||
var definitions = basePackage.LaunchOptions; |
||||
// Create config cards and save them |
||||
var cards = LaunchOptionCard |
||||
.FromDefinitions(definitions, Array.Empty<LaunchOption>()) |
||||
.ToImmutableArray(); |
||||
|
||||
var args = cards.SelectMany(c => c.Options).ToList(); |
||||
|
||||
logger.LogDebug( |
||||
"Setting initial launch args: {Args}", |
||||
string.Join(", ", args.Select(o => o.ToArgString()?.ToRepr())) |
||||
); |
||||
|
||||
settingsManager.SaveLaunchArgs(installedPackage.Id, args); |
||||
} |
||||
|
||||
if (basePackage is not StableSwarm) |
||||
{ |
||||
await pyRunner.Initialize(); |
||||
} |
||||
|
||||
// Get path from package |
||||
var packagePath = new DirectoryPath(settingsManager.LibraryDir, installedPackage.LibraryPath!); |
||||
|
||||
if (basePackage is not StableSwarm) |
||||
{ |
||||
// Unpack sitecustomize.py to venv |
||||
await UnpackSiteCustomize(packagePath.JoinDir("venv")); |
||||
} |
||||
|
||||
// Clear console and start update processing |
||||
var console = new ConsoleViewModel(); |
||||
console.StartUpdates(); |
||||
|
||||
// Update shared folder links (in case library paths changed) |
||||
await basePackage.UpdateModelFolders( |
||||
packagePath, |
||||
installedPackage.PreferredSharedFolderMethod ?? basePackage.RecommendedSharedFolderMethod |
||||
); |
||||
|
||||
// Load user launch args from settings and convert to string |
||||
var userArgs = installedPackage.LaunchArgs ?? []; |
||||
var userArgsString = string.Join(" ", userArgs.Select(opt => opt.ToArgString())); |
||||
|
||||
// Join with extras, if any |
||||
userArgsString = string.Join(" ", userArgsString, basePackage.ExtraLaunchArguments); |
||||
|
||||
// Use input command if provided, otherwise use package launch command |
||||
command ??= basePackage.LaunchCommand; |
||||
|
||||
await basePackage.RunPackage(packagePath, command, userArgsString, o => console.Post(o)); |
||||
var runningPackage = new PackagePair(installedPackage, basePackage); |
||||
|
||||
var viewModel = new RunningPackageViewModel( |
||||
settingsManager, |
||||
notificationService, |
||||
this, |
||||
runningPackage, |
||||
console |
||||
); |
||||
RunningPackages.Add(runningPackage.InstalledPackage.Id, viewModel); |
||||
|
||||
return runningPackage; |
||||
} |
||||
|
||||
public async Task StopPackage(Guid id) |
||||
{ |
||||
if (RunningPackages.TryGetValue(id, out var vm)) |
||||
{ |
||||
var runningPackage = vm.RunningPackage; |
||||
await runningPackage.BasePackage.WaitForShutdown(); |
||||
RunningPackages.Remove(id); |
||||
} |
||||
} |
||||
|
||||
public RunningPackageViewModel? GetRunningPackageViewModel(Guid id) => |
||||
RunningPackages.TryGetValue(id, out var vm) ? vm : null; |
||||
|
||||
private static async Task UnpackSiteCustomize(DirectoryPath venvPath) |
||||
{ |
||||
var sitePackages = venvPath.JoinDir(PyVenvRunner.RelativeSitePackagesPath); |
||||
var file = sitePackages.JoinFile("sitecustomize.py"); |
||||
file.Directory?.Create(); |
||||
await Assets.PyScriptSiteCustomize.ExtractTo(file, true); |
||||
} |
||||
} |
@ -0,0 +1,403 @@
|
||||
<Styles xmlns="https://github.com/avaloniaui" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"> |
||||
<Design.PreviewWith> |
||||
<Border Padding="20"> |
||||
<ui:CommandBar |
||||
Margin="8" |
||||
VerticalAlignment="Center" |
||||
VerticalContentAlignment="Center" |
||||
HorizontalAlignment="Left" |
||||
HorizontalContentAlignment="Left" |
||||
DefaultLabelPosition="Right"> |
||||
<ui:CommandBar.PrimaryCommands> |
||||
<ui:CommandBarButton Classes="success" Label="Success Button" Margin="8" |
||||
HorizontalAlignment="Center" /> |
||||
<ui:CommandBarButton Classes="accent" Label="FA Accent Button" Margin="8" |
||||
HorizontalAlignment="Center" /> |
||||
<ui:CommandBarButton Classes="systemaccent" Label="System Accent Button" Margin="8" |
||||
HorizontalAlignment="Center" /> |
||||
<ui:CommandBarButton Classes="danger" Label="Danger Button" Margin="8" HorizontalAlignment="Center" /> |
||||
<ui:CommandBarButton Classes="info" Label="Info Button" Margin="8" HorizontalAlignment="Center" /> |
||||
<ui:CommandBarButton Classes="transparent-info" Label="Semi-Transparent Info Button" Margin="8" |
||||
HorizontalAlignment="Center" /> |
||||
<ui:CommandBarButton Classes="transparent" Label="Transparent Button" Margin="8" |
||||
HorizontalAlignment="Center" /> |
||||
<ui:CommandBarButton Classes="transparent-full" Label="Transparent Button" Margin="8" |
||||
HorizontalAlignment="Center" /> |
||||
<ui:CommandBarButton Label="Disabled Button" Margin="8" IsEnabled="False" |
||||
HorizontalAlignment="Center" /> |
||||
</ui:CommandBar.PrimaryCommands> |
||||
</ui:CommandBar> |
||||
</Border> |
||||
</Design.PreviewWith> |
||||
|
||||
<!-- Success --> |
||||
<Style Selector="ui|CommandBarButton.success"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ThemeGreenColor}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ThemeGreenColor}" /> |
||||
</Style> |
||||
<Style Selector="^ /template/ TextBlock#TextLabel"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForeground}" /> |
||||
</Style> |
||||
|
||||
<Style Selector="^:pointerover"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ThemeDarkGreenColor}"/> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ThemeDarkGreenColor}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="Green" /> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<Style Selector="^:pressed"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ThemeDarkDarkGreenColor}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ThemeDarkDarkGreenColor}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPressed}" /> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<Style Selector="^:disabled"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundDisabled}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushDisabled}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundDisabled}" /> |
||||
</Style> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<!-- Danger --> |
||||
<Style Selector="ui|CommandBarButton.danger"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ThemeRedColor}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ThemeRedColor}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForeground}" /> |
||||
</Style> |
||||
|
||||
<Style Selector="^:pointerover"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ThemeDarkRedColor}"/> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ThemeDarkRedColor}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPointerOver}" /> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<Style Selector="^:pressed"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ThemeDarkDarkRedColor}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ThemeDarkDarkRedColor}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPressed}" /> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<Style Selector="^:disabled"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundDisabled}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushDisabled}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundDisabled}" /> |
||||
</Style> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<!-- Info --> |
||||
<Style Selector="ui|CommandBarButton.info"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ThemeLightBlueColor}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ThemeLightBlueColor}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForeground}" /> |
||||
</Style> |
||||
|
||||
<Style Selector="^:pointerover"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ThemeBlueColor}"/> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ThemeBlueColor}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPointerOver}" /> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<Style Selector="^:pressed"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ThemeDarkBlueColor}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ThemeDarkBlueColor}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPressed}" /> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<Style Selector="^:disabled"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundDisabled}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushDisabled}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundDisabled}" /> |
||||
</Style> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<!--Accent Button--> |
||||
<Style Selector="ui|CommandBarButton.accent"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource AccentButtonBackground}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource AccentButtonBorderBrush}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource AccentButtonForeground}" /> |
||||
</Style> |
||||
|
||||
<Style Selector="^:pointerover"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource AccentButtonBackgroundPointerOver}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource AccentButtonBorderBrushPointerOver}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource AccentButtonForegroundPointerOver}" /> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<Style Selector="^:pressed"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource AccentButtonBackgroundPressed}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource AccentButtonBorderBrushPressed}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource AccentButtonForegroundPressed}" /> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<Style Selector="^:disabled"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource AccentButtonBackgroundDisabled}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource AccentButtonBorderBrushDisabled}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource AccentButtonForegroundDisabled}" /> |
||||
</Style> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<!-- SystemAccent --> |
||||
<Style Selector="ui|CommandBarButton.systemaccent"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource SystemAccentColor}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource SystemAccentColor}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForeground}" /> |
||||
</Style> |
||||
|
||||
<Style Selector="^:pointerover"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource SystemAccentColorDark1}"/> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource SystemAccentColorDark1}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPointerOver}" /> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<Style Selector="^:pressed"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource SystemAccentColorDark2}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource SystemAccentColorDark2}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPressed}" /> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<Style Selector="^:disabled"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundDisabled}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushDisabled}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundDisabled}" /> |
||||
</Style> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<!-- Transparent --> |
||||
<Style Selector="ui|CommandBarButton.transparent"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource SystemControlTransparentBrush}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrush}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForeground}" /> |
||||
</Style> |
||||
|
||||
<Style Selector="^:pointerover"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundDisabled}"/> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBackgroundDisabled}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPointerOver}" /> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<Style Selector="^:pressed"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundPressed}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBackgroundPressed}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPressed}" /> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<Style Selector="^:disabled"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundDisabled}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushDisabled}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundDisabled}" /> |
||||
</Style> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<!-- Semi-Transparent Info --> |
||||
<Style Selector="ui|CommandBarButton.transparent-info"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ThemeLightBlueColorTransparent}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ThemeLightBlueColorTransparent}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForeground}" /> |
||||
</Style> |
||||
|
||||
<Style Selector="^:pointerover"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ThemeBlueColorTransparent}"/> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ThemeBlueColorTransparent}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPointerOver}" /> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<Style Selector="^:pressed"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ThemeDarkBlueColorTransparent}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ThemeDarkBlueColorTransparent}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPressed}" /> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<Style Selector="^:disabled"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundDisabled}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushDisabled}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundDisabled}" /> |
||||
</Style> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<!-- Transparent red --> |
||||
<Style Selector="ui|CommandBarButton.transparent-red"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource SystemControlTransparentBrush}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrush}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForeground}" /> |
||||
</Style> |
||||
|
||||
<Style Selector="^:pointerover"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ThemeCoralRedColor}"/> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ThemeCoralRedColor}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPointerOver}" /> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<Style Selector="^:pressed"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ThemeDarkCoralRedColor}"/> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ThemeDarkCoralRedColor}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPressed}" /> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<Style Selector="^:disabled"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundDisabled}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushDisabled}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundDisabled}" /> |
||||
</Style> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<!-- Full Transparent --> |
||||
<Style Selector="ui|CommandBarButton.transparent-full"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource SystemControlTransparentBrush}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource SystemControlTransparentBrush}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForeground}" /> |
||||
</Style> |
||||
|
||||
<Style Selector="^:pointerover"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundDisabled}"/> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBackgroundDisabled}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPointerOver}" /> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<Style Selector="^:pressed"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundPressed}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBackgroundPressed}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPressed}" /> |
||||
</Style> |
||||
</Style> |
||||
|
||||
<Style Selector="^:disabled"> |
||||
<Style Selector="^ /template/ Border#AppBarButtonInnerBorder"> |
||||
<Setter Property="Background" Value="{DynamicResource SystemControlTransparentBrush}" /> |
||||
<Setter Property="BorderBrush" Value="{DynamicResource SystemControlTransparentBrush}" /> |
||||
</Style> |
||||
<Style Selector="^"> |
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundDisabled}" /> |
||||
</Style> |
||||
</Style> |
||||
</Style> |
||||
</Styles> |
@ -0,0 +1,161 @@
|
||||
using System; |
||||
using System.Threading.Tasks; |
||||
using CommunityToolkit.Mvvm.ComponentModel; |
||||
using CommunityToolkit.Mvvm.Input; |
||||
using FluentAvalonia.UI.Controls; |
||||
using StabilityMatrix.Avalonia.Services; |
||||
using StabilityMatrix.Avalonia.ViewModels.Base; |
||||
using StabilityMatrix.Avalonia.Views; |
||||
using StabilityMatrix.Core.Attributes; |
||||
using StabilityMatrix.Core.Helper; |
||||
using StabilityMatrix.Core.Models; |
||||
using StabilityMatrix.Core.Models.Packages; |
||||
using StabilityMatrix.Core.Processes; |
||||
using StabilityMatrix.Core.Services; |
||||
using SymbolIconSource = FluentIcons.Avalonia.Fluent.SymbolIconSource; |
||||
using TeachingTip = StabilityMatrix.Core.Models.Settings.TeachingTip; |
||||
|
||||
namespace StabilityMatrix.Avalonia.ViewModels; |
||||
|
||||
[View(typeof(ConsoleOutputPage))] |
||||
public partial class RunningPackageViewModel : PageViewModelBase, IDisposable, IAsyncDisposable |
||||
{ |
||||
private readonly ISettingsManager settingsManager; |
||||
private readonly INotificationService notificationService; |
||||
private readonly RunningPackageService runningPackageService; |
||||
|
||||
public PackagePair RunningPackage { get; } |
||||
public ConsoleViewModel Console { get; } |
||||
public override string Title => RunningPackage.InstalledPackage.PackageName ?? "Running Package"; |
||||
public override IconSource IconSource => new SymbolIconSource(); |
||||
|
||||
[ObservableProperty] |
||||
private bool autoScrollToEnd; |
||||
|
||||
[ObservableProperty] |
||||
private bool showWebUiButton; |
||||
|
||||
[ObservableProperty] |
||||
private string webUiUrl = string.Empty; |
||||
|
||||
[ObservableProperty] |
||||
private bool isRunning = true; |
||||
|
||||
[ObservableProperty] |
||||
private string consoleInput = string.Empty; |
||||
|
||||
[ObservableProperty] |
||||
private bool showWebUiTeachingTip; |
||||
|
||||
/// <inheritdoc/> |
||||
public RunningPackageViewModel( |
||||
ISettingsManager settingsManager, |
||||
INotificationService notificationService, |
||||
RunningPackageService runningPackageService, |
||||
PackagePair runningPackage, |
||||
ConsoleViewModel console |
||||
) |
||||
{ |
||||
this.settingsManager = settingsManager; |
||||
this.notificationService = notificationService; |
||||
this.runningPackageService = runningPackageService; |
||||
|
||||
RunningPackage = runningPackage; |
||||
Console = console; |
||||
Console.Document.LineCountChanged += DocumentOnLineCountChanged; |
||||
RunningPackage.BasePackage.StartupComplete += BasePackageOnStartupComplete; |
||||
RunningPackage.BasePackage.Exited += BasePackageOnExited; |
||||
|
||||
settingsManager.RelayPropertyFor( |
||||
this, |
||||
vm => vm.AutoScrollToEnd, |
||||
settings => settings.AutoScrollLaunchConsoleToEnd, |
||||
true |
||||
); |
||||
} |
||||
|
||||
private void BasePackageOnExited(object? sender, int e) |
||||
{ |
||||
IsRunning = false; |
||||
ShowWebUiButton = false; |
||||
Console.Document.LineCountChanged -= DocumentOnLineCountChanged; |
||||
RunningPackage.BasePackage.StartupComplete -= BasePackageOnStartupComplete; |
||||
RunningPackage.BasePackage.Exited -= BasePackageOnExited; |
||||
runningPackageService.RunningPackages.Remove(RunningPackage.InstalledPackage.Id); |
||||
} |
||||
|
||||
private void BasePackageOnStartupComplete(object? sender, string url) |
||||
{ |
||||
WebUiUrl = url.Replace("0.0.0.0", "127.0.0.1"); |
||||
ShowWebUiButton = !string.IsNullOrWhiteSpace(WebUiUrl); |
||||
|
||||
if (settingsManager.Settings.SeenTeachingTips.Contains(TeachingTip.WebUiButtonMovedTip)) |
||||
return; |
||||
|
||||
ShowWebUiTeachingTip = true; |
||||
settingsManager.Transaction(s => s.SeenTeachingTips.Add(TeachingTip.WebUiButtonMovedTip)); |
||||
} |
||||
|
||||
private void DocumentOnLineCountChanged(object? sender, EventArgs e) |
||||
{ |
||||
if (AutoScrollToEnd) |
||||
{ |
||||
EventManager.Instance.OnScrollToBottomRequested(); |
||||
} |
||||
} |
||||
|
||||
[RelayCommand] |
||||
private void LaunchPackage() |
||||
{ |
||||
EventManager.Instance.OnPackageRelaunchRequested(RunningPackage.InstalledPackage); |
||||
} |
||||
|
||||
[RelayCommand] |
||||
private async Task Stop() |
||||
{ |
||||
await runningPackageService.StopPackage(RunningPackage.InstalledPackage.Id); |
||||
Console.PostLine($"{Environment.NewLine}Stopped process at {DateTimeOffset.Now}"); |
||||
await Console.StopUpdatesAsync(); |
||||
IsRunning = false; |
||||
} |
||||
|
||||
[RelayCommand] |
||||
private void LaunchWebUi() |
||||
{ |
||||
if (string.IsNullOrEmpty(WebUiUrl)) |
||||
return; |
||||
|
||||
notificationService.TryAsync( |
||||
Task.Run(() => ProcessRunner.OpenUrl(WebUiUrl)), |
||||
"Failed to open URL", |
||||
$"{WebUiUrl}" |
||||
); |
||||
} |
||||
|
||||
[RelayCommand] |
||||
private async Task SendToConsole() |
||||
{ |
||||
Console.PostLine(ConsoleInput); |
||||
if (RunningPackage?.BasePackage is BaseGitPackage gitPackage) |
||||
{ |
||||
var venv = gitPackage.VenvRunner; |
||||
var process = venv?.Process; |
||||
if (process is not null) |
||||
{ |
||||
await process.StandardInput.WriteLineAsync(ConsoleInput); |
||||
} |
||||
} |
||||
|
||||
ConsoleInput = string.Empty; |
||||
} |
||||
|
||||
public void Dispose() |
||||
{ |
||||
Console.Dispose(); |
||||
} |
||||
|
||||
public async ValueTask DisposeAsync() |
||||
{ |
||||
await Console.DisposeAsync(); |
||||
} |
||||
} |
@ -0,0 +1,93 @@
|
||||
<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:avaloniaEdit="https://github.com/avaloniaui/avaloniaedit" |
||||
xmlns:viewModels="clr-namespace:StabilityMatrix.Avalonia.ViewModels" |
||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" |
||||
xmlns:lang="clr-namespace:StabilityMatrix.Avalonia.Languages" |
||||
xmlns:avalonia="https://github.com/projektanker/icons.avalonia" |
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" |
||||
x:DataType="viewModels:RunningPackageViewModel" |
||||
x:Class="StabilityMatrix.Avalonia.Views.ConsoleOutputPage"> |
||||
<Grid RowDefinitions="Auto, *, Auto"> |
||||
<ui:CommandBar Grid.Row="0" |
||||
Margin="12,0,0,4" |
||||
VerticalAlignment="Center" |
||||
VerticalContentAlignment="Center" |
||||
HorizontalAlignment="Left" |
||||
HorizontalContentAlignment="Left" |
||||
DefaultLabelPosition="Right"> |
||||
<ui:CommandBar.PrimaryCommands> |
||||
<ui:CommandBarButton |
||||
IconSource="Stop" |
||||
IsVisible="{Binding IsRunning}" |
||||
Classes="danger" |
||||
Command="{Binding StopCommand}" |
||||
VerticalAlignment="Center" |
||||
Label="{x:Static lang:Resources.Action_Stop}" /> |
||||
<ui:CommandBarButton |
||||
IconSource="Play" |
||||
IsVisible="{Binding !IsRunning}" |
||||
Classes="success" |
||||
Command="{Binding LaunchPackageCommand}" |
||||
VerticalAlignment="Center" |
||||
Label="{x:Static lang:Resources.Action_Launch}" /> |
||||
|
||||
<ui:CommandBarSeparator Margin="6,0,4,0"/> |
||||
|
||||
<ui:CommandBarToggleButton |
||||
VerticalAlignment="Center" |
||||
IsChecked="{Binding AutoScrollToEnd}" |
||||
Label="{x:Static lang:Resources.Label_ToggleAutoScrolling}" |
||||
ToolTip.Tip="{x:Static lang:Resources.Label_AutoScrollToEnd}"> |
||||
<ui:CommandBarToggleButton.IconSource> |
||||
<controls:FASymbolIconSource Symbol="fa-solid fa-arrow-down-wide-short" /> |
||||
</ui:CommandBarToggleButton.IconSource> |
||||
</ui:CommandBarToggleButton> |
||||
|
||||
<ui:CommandBarButton |
||||
Command="{Binding LaunchWebUiCommand}" |
||||
IsVisible="{Binding ShowWebUiButton}" |
||||
VerticalAlignment="Center" |
||||
x:Name="OpenWebUiButton" |
||||
Label="{x:Static lang:Resources.Action_OpenWebUI}"> |
||||
<ui:CommandBarButton.IconSource> |
||||
<controls:FASymbolIconSource Symbol="fa-solid fa-up-right-from-square"/> |
||||
</ui:CommandBarButton.IconSource> |
||||
</ui:CommandBarButton> |
||||
</ui:CommandBar.PrimaryCommands> |
||||
</ui:CommandBar> |
||||
|
||||
<avaloniaEdit:TextEditor |
||||
Grid.Row="1" |
||||
x:Name="Console" |
||||
Margin="8,8,16,10" |
||||
DataContext="{Binding Console}" |
||||
Document="{Binding Document}" |
||||
FontFamily="Cascadia Code,Consolas,Menlo,Monospace" |
||||
IsReadOnly="True" |
||||
LineNumbersForeground="DarkSlateGray" |
||||
ShowLineNumbers="True" |
||||
VerticalScrollBarVisibility="Auto" |
||||
WordWrap="True" /> |
||||
|
||||
<Grid Grid.Row="2" ColumnDefinitions="*, Auto" |
||||
Margin="16,4,16,16"> |
||||
<TextBox Grid.Column="0" Text="{Binding ConsoleInput, Mode=TwoWay}" |
||||
Margin="0,0,8,0"/> |
||||
<Button Grid.Column="1" |
||||
Classes="accent" |
||||
IsDefault="True" |
||||
Content="{x:Static lang:Resources.Action_Send}" |
||||
Command="{Binding SendToConsoleCommand}"/> |
||||
</Grid> |
||||
|
||||
<ui:TeachingTip Grid.Row="0" Grid.Column="0" Name="TeachingTip1" |
||||
Target="{Binding #OpenWebUiButton}" |
||||
Title="{x:Static lang:Resources.TeachingTip_WebUiButtonMoved}" |
||||
PreferredPlacement="Bottom" |
||||
IsOpen="True"/> |
||||
</Grid> |
||||
</controls:UserControlBase> |
@ -0,0 +1,54 @@
|
||||
using System; |
||||
using Avalonia.Controls; |
||||
using Avalonia.Controls.Primitives; |
||||
using Avalonia.Interactivity; |
||||
using Avalonia.Threading; |
||||
using AvaloniaEdit; |
||||
using StabilityMatrix.Avalonia.Controls; |
||||
using StabilityMatrix.Avalonia.Helpers; |
||||
using StabilityMatrix.Avalonia.Models; |
||||
using StabilityMatrix.Core.Attributes; |
||||
using StabilityMatrix.Core.Helper; |
||||
|
||||
namespace StabilityMatrix.Avalonia.Views; |
||||
|
||||
[Transient] |
||||
public partial class ConsoleOutputPage : UserControlBase |
||||
{ |
||||
private const int LineOffset = 5; |
||||
|
||||
public ConsoleOutputPage() |
||||
{ |
||||
InitializeComponent(); |
||||
} |
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) |
||||
{ |
||||
base.OnApplyTemplate(e); |
||||
TextEditorConfigs.Configure(Console, TextEditorPreset.Console); |
||||
} |
||||
|
||||
protected override void OnUnloaded(RoutedEventArgs e) |
||||
{ |
||||
base.OnUnloaded(e); |
||||
EventManager.Instance.ScrollToBottomRequested -= OnScrollToBottomRequested; |
||||
} |
||||
|
||||
protected override void OnLoaded(RoutedEventArgs e) |
||||
{ |
||||
base.OnLoaded(e); |
||||
EventManager.Instance.ScrollToBottomRequested += OnScrollToBottomRequested; |
||||
} |
||||
|
||||
private void OnScrollToBottomRequested(object? sender, EventArgs e) |
||||
{ |
||||
Dispatcher.UIThread.Invoke(() => |
||||
{ |
||||
var editor = this.FindControl<TextEditor>("Console"); |
||||
if (editor?.Document == null) |
||||
return; |
||||
var line = Math.Max(editor.Document.LineCount - LineOffset, 1); |
||||
editor.ScrollToLine(line); |
||||
}); |
||||
} |
||||
} |
@ -0,0 +1,124 @@
|
||||
using System.Diagnostics.CodeAnalysis; |
||||
using JetBrains.Annotations; |
||||
|
||||
namespace StabilityMatrix.Core.Models.Api.Comfy; |
||||
|
||||
/// <summary> |
||||
/// Collection of preprocessors included in |
||||
/// </summary> |
||||
/// <param name="Value"></param> |
||||
[PublicAPI] |
||||
[SuppressMessage("ReSharper", "InconsistentNaming")] |
||||
public record ComfyAuxPreprocessor(string Value) : StringValue(Value) |
||||
{ |
||||
public static ComfyAuxPreprocessor None { get; } = new("none"); |
||||
public static ComfyAuxPreprocessor AnimeFaceSemSegPreprocessor { get; } = |
||||
new("AnimeFace_SemSegPreprocessor"); |
||||
public static ComfyAuxPreprocessor BinaryPreprocessor { get; } = new("BinaryPreprocessor"); |
||||
public static ComfyAuxPreprocessor CannyEdgePreprocessor { get; } = new("CannyEdgePreprocessor"); |
||||
public static ComfyAuxPreprocessor ColorPreprocessor { get; } = new("ColorPreprocessor"); |
||||
public static ComfyAuxPreprocessor DensePosePreprocessor { get; } = new("DensePosePreprocessor"); |
||||
public static ComfyAuxPreprocessor DepthAnythingPreprocessor { get; } = new("DepthAnythingPreprocessor"); |
||||
public static ComfyAuxPreprocessor ZoeDepthAnythingPreprocessor { get; } = |
||||
new("Zoe_DepthAnythingPreprocessor"); |
||||
public static ComfyAuxPreprocessor DiffusionEdgePreprocessor { get; } = new("DiffusionEdge_Preprocessor"); |
||||
public static ComfyAuxPreprocessor DWPreprocessor { get; } = new("DWPreprocessor"); |
||||
public static ComfyAuxPreprocessor AnimalPosePreprocessor { get; } = new("AnimalPosePreprocessor"); |
||||
public static ComfyAuxPreprocessor HEDPreprocessor { get; } = new("HEDPreprocessor"); |
||||
public static ComfyAuxPreprocessor FakeScribblePreprocessor { get; } = new("FakeScribblePreprocessor"); |
||||
public static ComfyAuxPreprocessor LeReSDepthMapPreprocessor { get; } = new("LeReS-DepthMapPreprocessor"); |
||||
public static ComfyAuxPreprocessor LineArtPreprocessor { get; } = new("LineArtPreprocessor"); |
||||
public static ComfyAuxPreprocessor AnimeLineArtPreprocessor { get; } = new("AnimeLineArtPreprocessor"); |
||||
public static ComfyAuxPreprocessor LineartStandardPreprocessor { get; } = |
||||
new("LineartStandardPreprocessor"); |
||||
public static ComfyAuxPreprocessor Manga2AnimeLineArtPreprocessor { get; } = |
||||
new("Manga2Anime_LineArt_Preprocessor"); |
||||
public static ComfyAuxPreprocessor MediaPipeFaceMeshPreprocessor { get; } = |
||||
new("MediaPipe-FaceMeshPreprocessor"); |
||||
public static ComfyAuxPreprocessor MeshGraphormerDepthMapPreprocessor { get; } = |
||||
new("MeshGraphormer-DepthMapPreprocessor"); |
||||
public static ComfyAuxPreprocessor MiDaSNormalMapPreprocessor { get; } = |
||||
new("MiDaS-NormalMapPreprocessor"); |
||||
public static ComfyAuxPreprocessor MiDaSDepthMapPreprocessor { get; } = new("MiDaS-DepthMapPreprocessor"); |
||||
public static ComfyAuxPreprocessor MLSDPreprocessor { get; } = new("M-LSDPreprocessor"); |
||||
public static ComfyAuxPreprocessor BAENormalMapPreprocessor { get; } = new("BAE-NormalMapPreprocessor"); |
||||
public static ComfyAuxPreprocessor OneFormerCOCOSemSegPreprocessor { get; } = |
||||
new("OneFormer-COCO-SemSegPreprocessor"); |
||||
public static ComfyAuxPreprocessor OneFormerADE20KSemSegPreprocessor { get; } = |
||||
new("OneFormer-ADE20K-SemSegPreprocessor"); |
||||
public static ComfyAuxPreprocessor OpenposePreprocessor { get; } = new("OpenposePreprocessor"); |
||||
public static ComfyAuxPreprocessor PiDiNetPreprocessor { get; } = new("PiDiNetPreprocessor"); |
||||
public static ComfyAuxPreprocessor SavePoseKpsAsJsonFile { get; } = new("SavePoseKpsAsJsonFile"); |
||||
public static ComfyAuxPreprocessor FacialPartColoringFromPoseKps { get; } = |
||||
new("FacialPartColoringFromPoseKps"); |
||||
public static ComfyAuxPreprocessor ImageLuminanceDetector { get; } = new("ImageLuminanceDetector"); |
||||
public static ComfyAuxPreprocessor ImageIntensityDetector { get; } = new("ImageIntensityDetector"); |
||||
public static ComfyAuxPreprocessor ScribblePreprocessor { get; } = new("ScribblePreprocessor"); |
||||
public static ComfyAuxPreprocessor ScribbleXDoGPreprocessor { get; } = new("Scribble_XDoG_Preprocessor"); |
||||
public static ComfyAuxPreprocessor SAMPreprocessor { get; } = new("SAMPreprocessor"); |
||||
public static ComfyAuxPreprocessor ShufflePreprocessor { get; } = new("ShufflePreprocessor"); |
||||
public static ComfyAuxPreprocessor TEEDPreprocessor { get; } = new("TEEDPreprocessor"); |
||||
public static ComfyAuxPreprocessor TilePreprocessor { get; } = new("TilePreprocessor"); |
||||
public static ComfyAuxPreprocessor UniFormerSemSegPreprocessor { get; } = |
||||
new("UniFormer-SemSegPreprocessor"); |
||||
public static ComfyAuxPreprocessor SemSegPreprocessor { get; } = new("SemSegPreprocessor"); |
||||
public static ComfyAuxPreprocessor UnimatchOptFlowPreprocessor { get; } = |
||||
new("Unimatch_OptFlowPreprocessor"); |
||||
public static ComfyAuxPreprocessor MaskOptFlow { get; } = new("MaskOptFlow"); |
||||
public static ComfyAuxPreprocessor ZoeDepthMapPreprocessor { get; } = new("Zoe-DepthMapPreprocessor"); |
||||
|
||||
private static Dictionary<ComfyAuxPreprocessor, string> DisplayNamesMapping { get; } = |
||||
new() |
||||
{ |
||||
[None] = "None", |
||||
[AnimeFaceSemSegPreprocessor] = "Anime Face SemSeg Preprocessor", |
||||
[BinaryPreprocessor] = "Binary Preprocessor", |
||||
[CannyEdgePreprocessor] = "Canny Edge Preprocessor", |
||||
[ColorPreprocessor] = "Color Preprocessor", |
||||
[DensePosePreprocessor] = "DensePose Preprocessor", |
||||
[DepthAnythingPreprocessor] = "Depth Anything Preprocessor", |
||||
[ZoeDepthAnythingPreprocessor] = "Zoe Depth Anything Preprocessor", |
||||
[DiffusionEdgePreprocessor] = "Diffusion Edge Preprocessor", |
||||
[DWPreprocessor] = "DW Preprocessor", |
||||
[AnimalPosePreprocessor] = "Animal Pose Preprocessor", |
||||
[HEDPreprocessor] = "HED Preprocessor", |
||||
[FakeScribblePreprocessor] = "Fake Scribble Preprocessor", |
||||
[LeReSDepthMapPreprocessor] = "LeReS-DepthMap Preprocessor", |
||||
[LineArtPreprocessor] = "LineArt Preprocessor", |
||||
[AnimeLineArtPreprocessor] = "Anime LineArt Preprocessor", |
||||
[LineartStandardPreprocessor] = "Lineart Standard Preprocessor", |
||||
[Manga2AnimeLineArtPreprocessor] = "Manga2Anime LineArt Preprocessor", |
||||
[MediaPipeFaceMeshPreprocessor] = "MediaPipe FaceMesh Preprocessor", |
||||
[MeshGraphormerDepthMapPreprocessor] = "MeshGraphormer DepthMap Preprocessor", |
||||
[MiDaSNormalMapPreprocessor] = "MiDaS NormalMap Preprocessor", |
||||
[MiDaSDepthMapPreprocessor] = "MiDaS DepthMap Preprocessor", |
||||
[MLSDPreprocessor] = "M-LSD Preprocessor", |
||||
[BAENormalMapPreprocessor] = "BAE NormalMap Preprocessor", |
||||
[OneFormerCOCOSemSegPreprocessor] = "OneFormer COCO SemSeg Preprocessor", |
||||
[OneFormerADE20KSemSegPreprocessor] = "OneFormer ADE20K SemSeg Preprocessor", |
||||
[OpenposePreprocessor] = "Openpose Preprocessor", |
||||
[PiDiNetPreprocessor] = "PiDiNet Preprocessor", |
||||
[SavePoseKpsAsJsonFile] = "Save Pose Kps As Json File", |
||||
[FacialPartColoringFromPoseKps] = "Facial Part Coloring From Pose Kps", |
||||
[ImageLuminanceDetector] = "Image Luminance Detector", |
||||
[ImageIntensityDetector] = "Image Intensity Detector", |
||||
[ScribblePreprocessor] = "Scribble Preprocessor", |
||||
[ScribbleXDoGPreprocessor] = "Scribble XDoG Preprocessor", |
||||
[SAMPreprocessor] = "SAM Preprocessor", |
||||
[ShufflePreprocessor] = "Shuffle Preprocessor", |
||||
[TEEDPreprocessor] = "TEED Preprocessor", |
||||
[TilePreprocessor] = "Tile Preprocessor", |
||||
[UniFormerSemSegPreprocessor] = "UniFormer SemSeg Preprocessor", |
||||
[SemSegPreprocessor] = "SemSeg Preprocessor", |
||||
[UnimatchOptFlowPreprocessor] = "Unimatch OptFlow Preprocessor", |
||||
[MaskOptFlow] = "Mask OptFlow", |
||||
[ZoeDepthMapPreprocessor] = "Zoe DepthMap Preprocessor" |
||||
}; |
||||
|
||||
public static IEnumerable<ComfyAuxPreprocessor> Defaults => DisplayNamesMapping.Keys; |
||||
|
||||
public string DisplayName => DisplayNamesMapping.GetValueOrDefault(this, Value); |
||||
|
||||
/// <inheritdoc /> |
||||
public override string ToString() => Value; |
||||
} |
@ -0,0 +1,14 @@
|
||||
using StabilityMatrix.Core.Models.Api.Comfy.Nodes; |
||||
|
||||
namespace StabilityMatrix.Core.Models; |
||||
|
||||
public class InferenceQueueCustomPromptEventArgs : EventArgs |
||||
{ |
||||
public ComfyNodeBuilder Builder { get; } = new(); |
||||
|
||||
public NodeDictionary Nodes => Builder.Nodes; |
||||
|
||||
public long? SeedOverride { get; init; } |
||||
|
||||
public List<(string SourcePath, string DestinationRelativePath)> FilesToTransfer { get; init; } = []; |
||||
} |
@ -0,0 +1,105 @@
|
||||
using System.Diagnostics.CodeAnalysis; |
||||
using System.Text.RegularExpressions; |
||||
using JetBrains.Annotations; |
||||
using Semver; |
||||
using StabilityMatrix.Core.Processes; |
||||
|
||||
namespace StabilityMatrix.Core.Models.Packages.Extensions; |
||||
|
||||
/// <summary> |
||||
/// Extension specifier with optional version constraints. |
||||
/// </summary> |
||||
[PublicAPI] |
||||
public partial class ExtensionSpecifier |
||||
{ |
||||
public required string Name { get; init; } |
||||
|
||||
public string? Constraint { get; init; } |
||||
|
||||
public string? Version { get; init; } |
||||
|
||||
public string? VersionConstraint => Constraint is null || Version is null ? null : Constraint + Version; |
||||
|
||||
public bool TryGetSemVersionRange([NotNullWhen(true)] out SemVersionRange? semVersionRange) |
||||
{ |
||||
if (!string.IsNullOrEmpty(VersionConstraint)) |
||||
{ |
||||
return SemVersionRange.TryParse( |
||||
VersionConstraint, |
||||
SemVersionRangeOptions.Loose, |
||||
out semVersionRange |
||||
); |
||||
} |
||||
|
||||
semVersionRange = null; |
||||
return false; |
||||
} |
||||
|
||||
public static ExtensionSpecifier Parse(string value) |
||||
{ |
||||
TryParse(value, true, out var packageSpecifier); |
||||
|
||||
return packageSpecifier!; |
||||
} |
||||
|
||||
public static bool TryParse(string value, [NotNullWhen(true)] out ExtensionSpecifier? extensionSpecifier) |
||||
{ |
||||
return TryParse(value, false, out extensionSpecifier); |
||||
} |
||||
|
||||
private static bool TryParse( |
||||
string value, |
||||
bool throwOnFailure, |
||||
[NotNullWhen(true)] out ExtensionSpecifier? packageSpecifier |
||||
) |
||||
{ |
||||
var match = ExtensionSpecifierRegex().Match(value); |
||||
if (!match.Success) |
||||
{ |
||||
if (throwOnFailure) |
||||
{ |
||||
throw new ArgumentException($"Invalid extension specifier: {value}"); |
||||
} |
||||
|
||||
packageSpecifier = null; |
||||
return false; |
||||
} |
||||
|
||||
packageSpecifier = new ExtensionSpecifier |
||||
{ |
||||
Name = match.Groups["extension_name"].Value, |
||||
Constraint = match.Groups["version_constraint"].Value, |
||||
Version = match.Groups["version"].Value |
||||
}; |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/// <inheritdoc /> |
||||
public override string ToString() |
||||
{ |
||||
return Name + VersionConstraint; |
||||
} |
||||
|
||||
public static implicit operator Argument(ExtensionSpecifier specifier) |
||||
{ |
||||
return specifier.VersionConstraint is null |
||||
? new Argument(specifier.Name) |
||||
: new Argument((specifier.Name, specifier.VersionConstraint)); |
||||
} |
||||
|
||||
public static implicit operator ExtensionSpecifier(string specifier) |
||||
{ |
||||
return Parse(specifier); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Regex to match a pip package specifier. |
||||
/// </summary> |
||||
[GeneratedRegex( |
||||
@"(?<extension_name>\S+)\s*(?<version_constraint>==|>=|<=|>|<|~=|!=)?\s*(?<version>[a-zA-Z0-9_.]+)?", |
||||
RegexOptions.CultureInvariant, |
||||
5000 |
||||
)] |
||||
private static partial Regex ExtensionSpecifierRegex(); |
||||
} |
Loading…
Reference in new issue