JT
11 months ago
28 changed files with 1281 additions and 94 deletions
@ -0,0 +1,88 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using Avalonia.Threading; |
||||
using CommunityToolkit.Mvvm.ComponentModel; |
||||
using FluentAvalonia.UI.Controls; |
||||
using Microsoft.Extensions.Logging; |
||||
using StabilityMatrix.Avalonia.Animations; |
||||
using StabilityMatrix.Avalonia.Services; |
||||
using StabilityMatrix.Avalonia.ViewModels.Base; |
||||
using StabilityMatrix.Avalonia.Views.Dialogs; |
||||
using StabilityMatrix.Core.Attributes; |
||||
using StabilityMatrix.Core.Helper; |
||||
using StabilityMatrix.Core.Helper.Factory; |
||||
using StabilityMatrix.Core.Models; |
||||
using StabilityMatrix.Core.Models.Packages; |
||||
using StabilityMatrix.Core.Python; |
||||
using StabilityMatrix.Core.Services; |
||||
|
||||
namespace StabilityMatrix.Avalonia.ViewModels.Dialogs; |
||||
|
||||
[View(typeof(NewInstallerDialog))] |
||||
[Transient, ManagedService] |
||||
public partial class NewInstallerDialogViewModel : PageViewModelBase |
||||
{ |
||||
private readonly INavigationService<NewPackageManagerViewModel> packageNavigationService; |
||||
private readonly ISettingsManager settingsManager; |
||||
private readonly INotificationService notificationService; |
||||
private readonly ILogger<PackageInstallDetailViewModel> logger; |
||||
private readonly IPyRunner pyRunner; |
||||
private readonly IPrerequisiteHelper prerequisiteHelper; |
||||
|
||||
[ObservableProperty] |
||||
private IEnumerable<BasePackage> inferencePackages; |
||||
|
||||
[ObservableProperty] |
||||
private IEnumerable<BasePackage> trainingPackages; |
||||
|
||||
public NewInstallerDialogViewModel( |
||||
IPackageFactory packageFactory, |
||||
INavigationService<NewPackageManagerViewModel> packageNavigationService, |
||||
ISettingsManager settingsManager, |
||||
INotificationService notificationService, |
||||
ILogger<PackageInstallDetailViewModel> logger, |
||||
IPyRunner pyRunner, |
||||
IPrerequisiteHelper prerequisiteHelper |
||||
) |
||||
{ |
||||
this.packageNavigationService = packageNavigationService; |
||||
this.settingsManager = settingsManager; |
||||
this.notificationService = notificationService; |
||||
this.logger = logger; |
||||
this.pyRunner = pyRunner; |
||||
this.prerequisiteHelper = prerequisiteHelper; |
||||
inferencePackages = packageFactory |
||||
.GetPackagesByType(PackageType.SdInference) |
||||
.OrderBy(p => p.InstallerSortOrder); |
||||
trainingPackages = packageFactory |
||||
.GetPackagesByType(PackageType.SdTraining) |
||||
.OrderBy(p => p.InstallerSortOrder); |
||||
} |
||||
|
||||
public override string Title => "Add Package"; |
||||
public override IconSource IconSource => new SymbolIconSource { Symbol = Symbol.Add }; |
||||
|
||||
public void OnPackageSelected(BaseGitPackage package) |
||||
{ |
||||
if (package is null) |
||||
{ |
||||
return; |
||||
} |
||||
|
||||
var vm = new PackageInstallDetailViewModel( |
||||
package, |
||||
settingsManager, |
||||
notificationService, |
||||
logger, |
||||
pyRunner, |
||||
prerequisiteHelper, |
||||
packageNavigationService |
||||
); |
||||
|
||||
Dispatcher.UIThread.Post( |
||||
() => packageNavigationService.NavigateTo(vm, BetterSlideNavigationTransition.PageSlideFromRight), |
||||
DispatcherPriority.Send |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,13 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel; |
||||
using StabilityMatrix.Avalonia.ViewModels.Base; |
||||
using StabilityMatrix.Core.Models.Packages.Extensions; |
||||
|
||||
namespace StabilityMatrix.Avalonia.ViewModels; |
||||
|
||||
public partial class ExtensionViewModel() : ViewModelBase |
||||
{ |
||||
[ObservableProperty] |
||||
private bool isSelected; |
||||
|
||||
public ExtensionBase Extension { get; init; } |
||||
} |
@ -0,0 +1,66 @@
|
||||
using System.Collections.Generic; |
||||
using System.Collections.ObjectModel; |
||||
using CommunityToolkit.Mvvm.ComponentModel; |
||||
using DynamicData; |
||||
using FluentAvalonia.UI.Controls; |
||||
using StabilityMatrix.Avalonia.Services; |
||||
using StabilityMatrix.Avalonia.ViewModels.Base; |
||||
using StabilityMatrix.Avalonia.ViewModels.Dialogs; |
||||
using StabilityMatrix.Avalonia.Views; |
||||
using StabilityMatrix.Core.Attributes; |
||||
using Symbol = FluentIcons.Common.Symbol; |
||||
using SymbolIconSource = FluentIcons.FluentAvalonia.SymbolIconSource; |
||||
|
||||
namespace StabilityMatrix.Avalonia.ViewModels; |
||||
|
||||
[View(typeof(NewPackageManagerPage))] |
||||
[Singleton] |
||||
public partial class NewPackageManagerViewModel : PageViewModelBase |
||||
{ |
||||
public override string Title => "Packages"; |
||||
public override IconSource IconSource => new SymbolIconSource { Symbol = Symbol.Box, IsFilled = true }; |
||||
|
||||
public IReadOnlyList<PageViewModelBase> SubPages { get; } |
||||
|
||||
[ObservableProperty] |
||||
private ObservableCollection<PageViewModelBase> currentPagePath = []; |
||||
|
||||
[ObservableProperty] |
||||
private PageViewModelBase? currentPage; |
||||
|
||||
public NewPackageManagerViewModel(ServiceManager<ViewModelBase> vmFactory) |
||||
{ |
||||
SubPages = new PageViewModelBase[] |
||||
{ |
||||
vmFactory.Get<PackageManagerViewModel>(), |
||||
vmFactory.Get<NewInstallerDialogViewModel>(), |
||||
}; |
||||
|
||||
CurrentPagePath.AddRange(SubPages); |
||||
|
||||
CurrentPage = SubPages[0]; |
||||
} |
||||
|
||||
partial void OnCurrentPageChanged(PageViewModelBase? value) |
||||
{ |
||||
if (value is null) |
||||
{ |
||||
return; |
||||
} |
||||
|
||||
if (value is PackageManagerViewModel) |
||||
{ |
||||
CurrentPagePath.Clear(); |
||||
CurrentPagePath.Add(value); |
||||
} |
||||
else if (value is PackageInstallDetailViewModel) |
||||
{ |
||||
CurrentPagePath.Add(value); |
||||
} |
||||
else |
||||
{ |
||||
CurrentPagePath.Clear(); |
||||
CurrentPagePath.AddRange(new[] { SubPages[0], value }); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,276 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Collections.ObjectModel; |
||||
using System.IO; |
||||
using System.Linq; |
||||
using System.Threading.Tasks; |
||||
using AsyncAwaitBestPractices; |
||||
using Avalonia.Controls; |
||||
using Avalonia.Controls.Notifications; |
||||
using CommunityToolkit.Mvvm.ComponentModel; |
||||
using CommunityToolkit.Mvvm.Input; |
||||
using FluentAvalonia.UI.Controls; |
||||
using Microsoft.Extensions.Logging; |
||||
using StabilityMatrix.Avalonia.Extensions; |
||||
using StabilityMatrix.Avalonia.Languages; |
||||
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.Database; |
||||
using StabilityMatrix.Core.Models.FileInterfaces; |
||||
using StabilityMatrix.Core.Models.PackageModification; |
||||
using StabilityMatrix.Core.Models.Packages; |
||||
using StabilityMatrix.Core.Python; |
||||
using StabilityMatrix.Core.Services; |
||||
using SymbolIconSource = FluentIcons.FluentAvalonia.SymbolIconSource; |
||||
|
||||
namespace StabilityMatrix.Avalonia.ViewModels; |
||||
|
||||
[View(typeof(PackageInstallDetailView))] |
||||
public partial class PackageInstallDetailViewModel( |
||||
BaseGitPackage package, |
||||
ISettingsManager settingsManager, |
||||
INotificationService notificationService, |
||||
ILogger<PackageInstallDetailViewModel> logger, |
||||
IPyRunner pyRunner, |
||||
IPrerequisiteHelper prerequisiteHelper, |
||||
INavigationService<NewPackageManagerViewModel> packageNavigationService |
||||
) : PageViewModelBase |
||||
{ |
||||
public BaseGitPackage SelectedPackage { get; } = package; |
||||
public override string Title { get; } = package.DisplayName; |
||||
public override IconSource IconSource => new SymbolIconSource(); |
||||
|
||||
public string FullInstallPath => Path.Combine(settingsManager.LibraryDir, "Packages", InstallName); |
||||
public bool ShowReleaseMode => SelectedPackage.ShouldIgnoreReleases == false; |
||||
|
||||
public string ReleaseLabelText => IsReleaseMode ? Resources.Label_Version : Resources.Label_Branch; |
||||
|
||||
public bool ShowTorchVersionOptions => SelectedTorchVersion != TorchVersion.None; |
||||
public bool ShowExtensions => SelectedPackage.AvailableExtensions.Any(); |
||||
|
||||
[ObservableProperty] |
||||
[NotifyPropertyChangedFor(nameof(FullInstallPath))] |
||||
private string installName = package.DisplayName; |
||||
|
||||
[ObservableProperty] |
||||
private bool showDuplicateWarning; |
||||
|
||||
[ObservableProperty] |
||||
[NotifyPropertyChangedFor(nameof(ReleaseLabelText))] |
||||
private bool isReleaseMode; |
||||
|
||||
[ObservableProperty] |
||||
private IEnumerable<PackageVersion> availableVersions = new List<PackageVersion>(); |
||||
|
||||
[ObservableProperty] |
||||
private PackageVersion? selectedVersion; |
||||
|
||||
[ObservableProperty] |
||||
private SharedFolderMethod selectedSharedFolderMethod; |
||||
|
||||
[ObservableProperty] |
||||
[NotifyPropertyChangedFor(nameof(ShowTorchVersionOptions))] |
||||
private TorchVersion selectedTorchVersion; |
||||
|
||||
[ObservableProperty] |
||||
private ObservableCollection<GitCommit>? availableCommits; |
||||
|
||||
[ObservableProperty] |
||||
private GitCommit? selectedCommit; |
||||
|
||||
[ObservableProperty] |
||||
private ObservableCollection<ExtensionViewModel> availableExtensions = []; |
||||
|
||||
private PackageVersionOptions? allOptions; |
||||
|
||||
public override async Task OnLoadedAsync() |
||||
{ |
||||
if (Design.IsDesignMode) |
||||
return; |
||||
|
||||
OnInstallNameChanged(InstallName); |
||||
AvailableExtensions = new ObservableCollection<ExtensionViewModel>( |
||||
SelectedPackage.AvailableExtensions.Select(p => new ExtensionViewModel { Extension = p }) |
||||
); |
||||
|
||||
allOptions = await SelectedPackage.GetAllVersionOptions(); |
||||
if (ShowReleaseMode) |
||||
{ |
||||
IsReleaseMode = true; |
||||
} |
||||
else |
||||
{ |
||||
UpdateVersions(); |
||||
await UpdateCommits(SelectedPackage.MainBranch); |
||||
} |
||||
} |
||||
|
||||
[RelayCommand] |
||||
private async Task Install() |
||||
{ |
||||
if (string.IsNullOrWhiteSpace(InstallName)) |
||||
{ |
||||
notificationService.Show( |
||||
new Notification( |
||||
"Package name is empty", |
||||
"Please enter a name for the package", |
||||
NotificationType.Error |
||||
) |
||||
); |
||||
return; |
||||
} |
||||
|
||||
var setPackageInstallingStep = new SetPackageInstallingStep(settingsManager, InstallName); |
||||
|
||||
var installLocation = Path.Combine(settingsManager.LibraryDir, "Packages", InstallName); |
||||
if (Directory.Exists(installLocation)) |
||||
{ |
||||
var installPath = new DirectoryPath(installLocation); |
||||
await installPath.DeleteVerboseAsync(logger); |
||||
} |
||||
|
||||
var prereqStep = new SetupPrerequisitesStep(prerequisiteHelper, pyRunner); |
||||
|
||||
var downloadOptions = new DownloadPackageVersionOptions(); |
||||
var installedVersion = new InstalledPackageVersion(); |
||||
if (IsReleaseMode) |
||||
{ |
||||
downloadOptions.VersionTag = |
||||
SelectedVersion?.TagName ?? throw new NullReferenceException("Selected version is null"); |
||||
downloadOptions.IsLatest = AvailableVersions?.First().TagName == downloadOptions.VersionTag; |
||||
downloadOptions.IsPrerelease = SelectedVersion.IsPrerelease; |
||||
|
||||
installedVersion.InstalledReleaseVersion = downloadOptions.VersionTag; |
||||
installedVersion.IsPrerelease = SelectedVersion.IsPrerelease; |
||||
} |
||||
else |
||||
{ |
||||
downloadOptions.CommitHash = |
||||
SelectedCommit?.Sha ?? throw new NullReferenceException("Selected commit is null"); |
||||
downloadOptions.BranchName = |
||||
SelectedVersion?.TagName ?? throw new NullReferenceException("Selected version is null"); |
||||
downloadOptions.IsLatest = AvailableCommits?.First().Sha == SelectedCommit.Sha; |
||||
|
||||
installedVersion.InstalledBranch = |
||||
SelectedVersion?.TagName ?? throw new NullReferenceException("Selected version is null"); |
||||
installedVersion.InstalledCommitSha = downloadOptions.CommitHash; |
||||
} |
||||
|
||||
var downloadStep = new DownloadPackageVersionStep(SelectedPackage, installLocation, downloadOptions); |
||||
var installStep = new InstallPackageStep( |
||||
SelectedPackage, |
||||
SelectedTorchVersion, |
||||
SelectedSharedFolderMethod, |
||||
downloadOptions, |
||||
installLocation |
||||
); |
||||
var installExtensionSteps = AvailableExtensions |
||||
.Where(e => e.IsSelected) |
||||
.Select( |
||||
e => |
||||
new InstallExtensionStep( |
||||
e.Extension, |
||||
Path.Combine(installLocation, SelectedPackage.ExtensionsFolderName) |
||||
) |
||||
) |
||||
.ToList(); |
||||
|
||||
var setupModelFoldersStep = new SetupModelFoldersStep( |
||||
SelectedPackage, |
||||
SelectedSharedFolderMethod, |
||||
installLocation |
||||
); |
||||
|
||||
var package = new InstalledPackage |
||||
{ |
||||
DisplayName = InstallName, |
||||
LibraryPath = Path.Combine("Packages", InstallName), |
||||
Id = Guid.NewGuid(), |
||||
PackageName = SelectedPackage.Name, |
||||
Version = installedVersion, |
||||
LaunchCommand = SelectedPackage.LaunchCommand, |
||||
LastUpdateCheck = DateTimeOffset.Now, |
||||
PreferredTorchVersion = SelectedTorchVersion, |
||||
PreferredSharedFolderMethod = SelectedSharedFolderMethod |
||||
}; |
||||
|
||||
var addInstalledPackageStep = new AddInstalledPackageStep(settingsManager, package); |
||||
|
||||
var steps = new List<IPackageStep> |
||||
{ |
||||
setPackageInstallingStep, |
||||
prereqStep, |
||||
downloadStep, |
||||
installStep, |
||||
}; |
||||
|
||||
if (installExtensionSteps.Count > 0) |
||||
{ |
||||
steps.AddRange(installExtensionSteps); |
||||
} |
||||
|
||||
steps.Add(setupModelFoldersStep); |
||||
steps.Add(addInstalledPackageStep); |
||||
|
||||
var runner = new PackageModificationRunner { ShowDialogOnStart = true }; |
||||
EventManager.Instance.OnPackageInstallProgressAdded(runner); |
||||
await runner.ExecuteSteps(steps.ToList()); |
||||
|
||||
if (!runner.Failed) |
||||
{ |
||||
EventManager.Instance.OnInstalledPackagesChanged(); |
||||
notificationService.Show( |
||||
"Package Install Complete", |
||||
$"{InstallName} installed successfully", |
||||
NotificationType.Success |
||||
); |
||||
packageNavigationService.GoBack(); |
||||
packageNavigationService.GoBack(); |
||||
} |
||||
} |
||||
|
||||
private void UpdateVersions() |
||||
{ |
||||
AvailableVersions = |
||||
IsReleaseMode && ShowReleaseMode ? allOptions.AvailableVersions : allOptions.AvailableBranches; |
||||
|
||||
SelectedVersion = !IsReleaseMode |
||||
? AvailableVersions?.FirstOrDefault(x => x.TagName == SelectedPackage.MainBranch) |
||||
?? AvailableVersions?.FirstOrDefault() |
||||
: AvailableVersions?.FirstOrDefault(); |
||||
} |
||||
|
||||
private async Task UpdateCommits(string branchName) |
||||
{ |
||||
var commits = await SelectedPackage.GetAllCommits(branchName); |
||||
if (commits != null) |
||||
{ |
||||
AvailableCommits = new ObservableCollection<GitCommit>(commits); |
||||
SelectedCommit = AvailableCommits.FirstOrDefault(); |
||||
} |
||||
} |
||||
|
||||
partial void OnInstallNameChanged(string? value) |
||||
{ |
||||
ShowDuplicateWarning = settingsManager.Settings.InstalledPackages.Any( |
||||
p => p.LibraryPath == $"Packages{Path.DirectorySeparatorChar}{value}" |
||||
); |
||||
} |
||||
|
||||
partial void OnIsReleaseModeChanged(bool value) |
||||
{ |
||||
UpdateVersions(); |
||||
} |
||||
|
||||
partial void OnSelectedVersionChanged(PackageVersion? value) |
||||
{ |
||||
if (IsReleaseMode) |
||||
return; |
||||
|
||||
UpdateCommits(value?.TagName ?? SelectedPackage.MainBranch).SafeFireAndForget(); |
||||
} |
||||
} |
@ -0,0 +1,233 @@
|
||||
<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:mocks="clr-namespace:StabilityMatrix.Avalonia.DesignData" |
||||
xmlns:packages="clr-namespace:StabilityMatrix.Core.Models.Packages;assembly=StabilityMatrix.Core" |
||||
xmlns:models="clr-namespace:StabilityMatrix.Core.Models;assembly=StabilityMatrix.Core" |
||||
xmlns:controls1="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" |
||||
xmlns:input="clr-namespace:FluentAvalonia.UI.Input;assembly=FluentAvalonia" |
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" |
||||
x:DataType="dialogs:NewInstallerDialogViewModel" |
||||
d:DataContext="{x:Static mocks:DesignData.NewInstallerDialogViewModel}" |
||||
x:Class="StabilityMatrix.Avalonia.Views.Dialogs.NewInstallerDialog"> |
||||
|
||||
<controls:UserControlBase.Resources> |
||||
<input:StandardUICommand x:Key="PackageSelected" |
||||
Command="{Binding OnPackageSelected}"/> |
||||
|
||||
<DataTemplate x:DataType="packages:BaseGitPackage" x:Key="PackageTemplate"> |
||||
<Button Padding="0" |
||||
HorizontalAlignment="Stretch" |
||||
HorizontalContentAlignment="Stretch" |
||||
Margin="4" |
||||
Classes="transparent-full" |
||||
CornerRadius="8" |
||||
Command="{StaticResource PackageSelected}" |
||||
CommandParameter="{Binding }"> |
||||
<controls:Card> |
||||
|
||||
<Grid RowDefinitions="Auto, Auto, Auto, Auto" |
||||
ColumnDefinitions="Auto, *, Auto"> |
||||
<controls:BetterAdvancedImage |
||||
Grid.Row="0" |
||||
Grid.RowSpan="4" |
||||
Grid.Column="0" |
||||
MaxHeight="128" |
||||
MaxWidth="128" |
||||
Stretch="UniformToFill" |
||||
CornerRadius="4" |
||||
Source="{Binding PreviewImageUri}" /> |
||||
<TextBlock Grid.Row="0" |
||||
Grid.Column="1" |
||||
Text="{Binding DisplayName}" |
||||
FontWeight="Light" |
||||
Margin="16,0,0,0" |
||||
FontSize="20" /> |
||||
<TextBlock Grid.Row="1" |
||||
Grid.Column="1" |
||||
Text="{Binding ByAuthor}" |
||||
FontWeight="Light" |
||||
Margin="16,-4,0,0" |
||||
FontSize="13" /> |
||||
|
||||
<TextBlock Grid.Row="0" |
||||
Grid.RowSpan="4" |
||||
Grid.Column="1" |
||||
TextWrapping="Wrap" |
||||
Text="{Binding Blurb}" |
||||
FontWeight="Light" |
||||
Margin="16,0,0,0" |
||||
VerticalAlignment="Center" |
||||
FontSize="16" /> |
||||
|
||||
<ItemsRepeater Grid.Column="1" |
||||
Grid.Row="3" |
||||
Margin="16, 8, 0, 8" |
||||
ItemsSource="{Binding AvailableTorchVersions}"> |
||||
<ItemsRepeater.Layout> |
||||
<StackLayout Orientation="Horizontal" /> |
||||
</ItemsRepeater.Layout> |
||||
<ItemsRepeater.ItemTemplate> |
||||
<DataTemplate DataType="{x:Type models:TorchVersion}"> |
||||
<controls:Card |
||||
Tag="{Binding }" |
||||
HorizontalAlignment="Left" |
||||
Padding="4" |
||||
Margin="0,0,8,0" |
||||
VerticalAlignment="Top"> |
||||
|
||||
<controls:Card.Styles> |
||||
<Style Selector="controls|Card[Tag=Cuda]"> |
||||
<Setter Property="Background" |
||||
Value="{DynamicResource ThemeGreenColorTransparent}" /> |
||||
<Setter Property="BorderBrush" |
||||
Value="{DynamicResource ThemeGreenColorTransparent}" /> |
||||
<Style |
||||
Selector="^ /template/ ContentPresenter#PART_ContentPresenter"> |
||||
<Setter Property="Foreground" |
||||
Value="{DynamicResource ButtonForeground}" /> |
||||
</Style> |
||||
<Setter Property="Content"> |
||||
<Template> |
||||
<TextBlock |
||||
FontWeight="Medium" |
||||
HorizontalAlignment="Center" |
||||
Text="NVIDIA" |
||||
TextAlignment="Center" |
||||
VerticalAlignment="Center" /> |
||||
</Template> |
||||
</Setter> |
||||
</Style> |
||||
<Style Selector="controls|Card[Tag=Rocm]"> |
||||
<Setter Property="Background" |
||||
Value="{DynamicResource ThemeDarkRedColor}" /> |
||||
<Setter Property="BorderBrush" |
||||
Value="{DynamicResource ThemeDarkRedColor}" /> |
||||
<Style |
||||
Selector="^ /template/ ContentPresenter#PART_ContentPresenter"> |
||||
<Setter Property="Foreground" |
||||
Value="{DynamicResource ButtonForeground}" /> |
||||
</Style> |
||||
<Setter Property="Content"> |
||||
<Template> |
||||
<TextBlock |
||||
FontWeight="Medium" |
||||
HorizontalAlignment="Center" |
||||
Text="AMD (Linux)" |
||||
TextAlignment="Center" |
||||
VerticalAlignment="Center" |
||||
ToolTip.Tip="For AMD GPUs that support ROCm on Linux" /> |
||||
</Template> |
||||
</Setter> |
||||
</Style> |
||||
<Style Selector="controls|Card[Tag=DirectMl]"> |
||||
<Setter Property="Background" |
||||
Value="{DynamicResource ThemeDarkBlueColor}" /> |
||||
<Setter Property="BorderBrush" |
||||
Value="{DynamicResource ThemeDarkBlueColor}" /> |
||||
<Setter Property="Content"> |
||||
<Template> |
||||
<TextBlock |
||||
FontWeight="Medium" |
||||
HorizontalAlignment="Center" |
||||
Text="DirectML" |
||||
TextAlignment="Center" |
||||
VerticalAlignment="Center" |
||||
ToolTip.Tip="For any DirectX compatible GPU on Windows" /> |
||||
</Template> |
||||
</Setter> |
||||
</Style> |
||||
<Style Selector="controls|Card[Tag=Mps]"> |
||||
<Setter Property="Background" Value="White" /> |
||||
<Setter Property="BorderBrush" Value="White" /> |
||||
<Style |
||||
Selector="^ /template/ ContentPresenter#PART_ContentPresenter"> |
||||
<Setter Property="Foreground" |
||||
Value="{DynamicResource ButtonForeground}" /> |
||||
</Style> |
||||
<Setter Property="Content"> |
||||
<Template> |
||||
<TextBlock |
||||
FontWeight="Medium" |
||||
HorizontalAlignment="Center" |
||||
Text="macOS" |
||||
TextAlignment="Center" |
||||
Foreground="Black" |
||||
VerticalAlignment="Center" /> |
||||
</Template> |
||||
</Setter> |
||||
</Style> |
||||
<Style Selector="controls|Card[Tag=Cpu]"> |
||||
<Setter Property="Background" |
||||
Value="{DynamicResource ThemeBlueGreyColor}" /> |
||||
<Setter Property="BorderBrush" |
||||
Value="{DynamicResource ThemeBlueGreyColor}" /> |
||||
<Style |
||||
Selector="^ /template/ ContentPresenter#PART_ContentPresenter"> |
||||
<Setter Property="Foreground" |
||||
Value="{DynamicResource ButtonForeground}" /> |
||||
</Style> |
||||
<Setter Property="Content"> |
||||
<Template> |
||||
<TextBlock |
||||
FontWeight="Medium" |
||||
HorizontalAlignment="Center" |
||||
Text="CPU" |
||||
TextAlignment="Center" |
||||
VerticalAlignment="Center" /> |
||||
</Template> |
||||
</Setter> |
||||
</Style> |
||||
</controls:Card.Styles> |
||||
</controls:Card> |
||||
</DataTemplate> |
||||
</ItemsRepeater.ItemTemplate> |
||||
</ItemsRepeater> |
||||
|
||||
<controls1:SymbolIcon Grid.Row="0" |
||||
Grid.RowSpan="4" |
||||
Grid.Column="2" |
||||
HorizontalAlignment="Right" |
||||
VerticalAlignment="Center" |
||||
FontSize="24" |
||||
Symbol="ChevronRight" /> |
||||
</Grid> |
||||
</controls:Card> |
||||
</Button> |
||||
</DataTemplate> |
||||
</controls:UserControlBase.Resources> |
||||
|
||||
<Grid> |
||||
<TabControl TabStripPlacement="Top"> |
||||
<TabControl.Items> |
||||
<TabItem Header="Inference" Margin="8,0,0,0"> |
||||
<ScrollViewer Padding="8"> |
||||
<ItemsRepeater ItemsSource="{Binding InferencePackages}"> |
||||
<ItemsRepeater.Layout> |
||||
<StackLayout Orientation="Vertical" /> |
||||
</ItemsRepeater.Layout> |
||||
<ItemsRepeater.ItemTemplate> |
||||
<StaticResource ResourceKey="PackageTemplate" /> |
||||
</ItemsRepeater.ItemTemplate> |
||||
</ItemsRepeater> |
||||
</ScrollViewer> |
||||
</TabItem> |
||||
<TabItem Header="Training"> |
||||
<ScrollViewer Padding="8"> |
||||
<ItemsRepeater ItemsSource="{Binding TrainingPackages}"> |
||||
<ItemsRepeater.Layout> |
||||
<StackLayout Orientation="Vertical" /> |
||||
</ItemsRepeater.Layout> |
||||
<ItemsRepeater.ItemTemplate> |
||||
<StaticResource ResourceKey="PackageTemplate" /> |
||||
</ItemsRepeater.ItemTemplate> |
||||
</ItemsRepeater> |
||||
</ScrollViewer> |
||||
</TabItem> |
||||
</TabControl.Items> |
||||
</TabControl> |
||||
</Grid> |
||||
</controls:UserControlBase> |
@ -0,0 +1,13 @@
|
||||
using StabilityMatrix.Avalonia.Controls; |
||||
using StabilityMatrix.Core.Attributes; |
||||
|
||||
namespace StabilityMatrix.Avalonia.Views.Dialogs; |
||||
|
||||
[Singleton] |
||||
public partial class NewInstallerDialog : UserControlBase |
||||
{ |
||||
public NewInstallerDialog() |
||||
{ |
||||
InitializeComponent(); |
||||
} |
||||
} |
@ -0,0 +1,49 @@
|
||||
<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:viewModels="clr-namespace:StabilityMatrix.Avalonia.ViewModels" |
||||
xmlns:controls="clr-namespace:StabilityMatrix.Avalonia.Controls" |
||||
xmlns:designData="clr-namespace:StabilityMatrix.Avalonia.DesignData" |
||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia.BreadcrumbBar" |
||||
xmlns:controls1="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" |
||||
xmlns:avalonia="clr-namespace:StabilityMatrix.Avalonia" |
||||
xmlns:base="clr-namespace:StabilityMatrix.Avalonia.ViewModels.Base" |
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" |
||||
x:DataType="viewModels:NewPackageManagerViewModel" |
||||
x:CompileBindings="True" |
||||
d:DataContext="{x:Static designData:DesignData.NewPackageManagerViewModel}" |
||||
x:Class="StabilityMatrix.Avalonia.Views.NewPackageManagerPage"> |
||||
|
||||
<controls:UserControlBase.Resources> |
||||
<!-- Override styles for BreadcrumbBar --> |
||||
<!-- ReSharper disable Xaml.RedundantResource --> |
||||
<x:Double x:Key="BreadcrumbBarItemThemeFontSize">24</x:Double> |
||||
<x:Double x:Key="BreadcrumbBarChevronFontSize">17</x:Double> |
||||
<Thickness x:Key="BreadcrumbBarChevronPadding">6,3</Thickness> |
||||
<FontWeight x:Key="BreadcrumbBarItemFontWeight">Medium</FontWeight> |
||||
<!-- ReSharper restore Xaml.RedundantResource --> |
||||
</controls:UserControlBase.Resources> |
||||
|
||||
<Grid RowDefinitions="Auto,*"> |
||||
<ui:BreadcrumbBar |
||||
Grid.Row="0" |
||||
Margin="16,8" |
||||
x:Name="BreadcrumbBar" |
||||
ItemsSource="{Binding CurrentPagePath}"> |
||||
<ui:BreadcrumbBar.ItemTemplate> |
||||
<DataTemplate x:DataType="base:PageViewModelBase"> |
||||
<ui:BreadcrumbBarItem Content="{Binding Title}" /> |
||||
</DataTemplate> |
||||
</ui:BreadcrumbBar.ItemTemplate> |
||||
</ui:BreadcrumbBar> |
||||
|
||||
<controls1:Frame |
||||
Grid.Row="1" |
||||
Name="FrameView"> |
||||
<controls1:Frame.NavigationPageFactory> |
||||
<avalonia:ViewLocator/> |
||||
</controls1:Frame.NavigationPageFactory> |
||||
</controls1:Frame> |
||||
</Grid> |
||||
</controls:UserControlBase> |
@ -0,0 +1,99 @@
|
||||
using System; |
||||
using System.ComponentModel; |
||||
using System.Linq; |
||||
using Avalonia.Interactivity; |
||||
using Avalonia.Threading; |
||||
using FluentAvalonia.UI.Controls; |
||||
using FluentAvalonia.UI.Media.Animation; |
||||
using FluentAvalonia.UI.Navigation; |
||||
using Microsoft.Extensions.DependencyInjection; |
||||
using StabilityMatrix.Avalonia.Animations; |
||||
using StabilityMatrix.Avalonia.Controls; |
||||
using StabilityMatrix.Avalonia.Models; |
||||
using StabilityMatrix.Avalonia.Services; |
||||
using StabilityMatrix.Avalonia.ViewModels; |
||||
using StabilityMatrix.Avalonia.ViewModels.Base; |
||||
using StabilityMatrix.Core.Attributes; |
||||
using StabilityMatrix.Core.Models; |
||||
|
||||
namespace StabilityMatrix.Avalonia.Views; |
||||
|
||||
[Singleton] |
||||
public partial class NewPackageManagerPage : UserControlBase, IHandleNavigation |
||||
{ |
||||
private readonly INavigationService<NewPackageManagerViewModel> packageNavigationService; |
||||
|
||||
private bool hasLoaded; |
||||
|
||||
private NewPackageManagerViewModel ViewModel => (NewPackageManagerViewModel)DataContext!; |
||||
|
||||
[DesignOnly(true)] |
||||
[Obsolete("For XAML use only", true)] |
||||
public NewPackageManagerPage() |
||||
: this(App.Services.GetRequiredService<INavigationService<NewPackageManagerViewModel>>()) { } |
||||
|
||||
public NewPackageManagerPage(INavigationService<NewPackageManagerViewModel> packageNavigationService) |
||||
{ |
||||
this.packageNavigationService = packageNavigationService; |
||||
|
||||
InitializeComponent(); |
||||
|
||||
packageNavigationService.SetFrame(FrameView); |
||||
packageNavigationService.TypedNavigation += NavigationService_OnTypedNavigation; |
||||
FrameView.Navigated += FrameView_Navigated; |
||||
BreadcrumbBar.ItemClicked += BreadcrumbBar_ItemClicked; |
||||
} |
||||
|
||||
/// <inheritdoc /> |
||||
protected override void OnLoaded(RoutedEventArgs e) |
||||
{ |
||||
base.OnLoaded(e); |
||||
|
||||
if (!hasLoaded) |
||||
{ |
||||
// Initial load, navigate to first page |
||||
Dispatcher.UIThread.Post( |
||||
() => |
||||
packageNavigationService.NavigateTo( |
||||
ViewModel.SubPages[0], |
||||
new SuppressNavigationTransitionInfo() |
||||
) |
||||
); |
||||
|
||||
hasLoaded = true; |
||||
} |
||||
} |
||||
|
||||
private void NavigationService_OnTypedNavigation(object? sender, TypedNavigationEventArgs e) |
||||
{ |
||||
ViewModel.CurrentPage = |
||||
ViewModel.SubPages.FirstOrDefault(x => x.GetType() == e.ViewModelType) |
||||
?? e.ViewModel as PageViewModelBase; |
||||
} |
||||
|
||||
private void FrameView_Navigated(object? sender, NavigationEventArgs args) |
||||
{ |
||||
if (args.Content is not PageViewModelBase vm) |
||||
{ |
||||
return; |
||||
} |
||||
|
||||
ViewModel.CurrentPage = vm; |
||||
} |
||||
|
||||
private void BreadcrumbBar_ItemClicked(BreadcrumbBar sender, BreadcrumbBarItemClickedEventArgs args) |
||||
{ |
||||
// Skip if already on same page |
||||
if (args.Item is not PageViewModelBase viewModel || viewModel == ViewModel.CurrentPage) |
||||
{ |
||||
return; |
||||
} |
||||
|
||||
packageNavigationService.NavigateTo(viewModel, BetterSlideNavigationTransition.PageSlideFromLeft); |
||||
} |
||||
|
||||
public bool GoBack() |
||||
{ |
||||
return packageNavigationService.GoBack(); |
||||
} |
||||
} |
@ -0,0 +1,195 @@
|
||||
<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: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" |
||||
xmlns:avalonia="clr-namespace:FluentIcons.Avalonia;assembly=FluentIcons.Avalonia" |
||||
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" |
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" |
||||
x:DataType="viewModels:PackageInstallDetailViewModel" |
||||
x:CompileBindings="True" |
||||
d:DataContext="{x:Static designData:DesignData.PackageInstallDetailViewModel}" |
||||
x:Class="StabilityMatrix.Avalonia.Views.PackageInstallDetailView"> |
||||
|
||||
<Grid ColumnDefinitions="Auto, *" |
||||
RowDefinitions="Auto, *"> |
||||
<controls:BetterAdvancedImage |
||||
MaxHeight="300" |
||||
MaxWidth="300" |
||||
Margin="16,16,8,8" |
||||
CornerRadius="8" |
||||
VerticalAlignment="Top" |
||||
Stretch="UniformToFill" |
||||
Source="{Binding SelectedPackage.PreviewImageUri}" /> |
||||
<StackPanel Grid.Row="0" Grid.Column="1" |
||||
Margin="8" |
||||
Orientation="Vertical"> |
||||
|
||||
<controls:HyperlinkIconButton NavigateUri="{Binding SelectedPackage.LicenseUrl}" |
||||
Content="{Binding SelectedPackage.LicenseType}"/> |
||||
|
||||
<ToggleSwitch OnContent="{x:Static lang:Resources.Label_Releases}" |
||||
OffContent="{x:Static lang:Resources.Label_Branches}" |
||||
IsVisible="{Binding ShowReleaseMode}" |
||||
IsChecked="{Binding IsReleaseMode}" |
||||
Margin="8,0,8,8" /> |
||||
|
||||
<!-- Version Selector --> |
||||
<Label Margin="8,0" |
||||
FontSize="14" |
||||
FontWeight="Light" |
||||
Content="{Binding ReleaseLabelText}" /> |
||||
|
||||
<controls1:FAComboBox |
||||
ItemsSource="{Binding AvailableVersions}" |
||||
MinWidth="250" |
||||
HorizontalAlignment="Stretch" |
||||
VerticalAlignment="Stretch" |
||||
FontSize="16" |
||||
Margin="8,0,8,8" |
||||
SelectedItem="{Binding SelectedVersion}"> |
||||
<controls1:FAComboBox.ItemTemplate> |
||||
<DataTemplate DataType="{x:Type models:PackageVersion}"> |
||||
<TextBlock |
||||
Name="NameTextBlock" |
||||
VerticalAlignment="Center" |
||||
Text="{Binding TagName}" /> |
||||
</DataTemplate> |
||||
</controls1:FAComboBox.ItemTemplate> |
||||
</controls1:FAComboBox> |
||||
|
||||
<Label Margin="8,0" |
||||
FontSize="14" |
||||
FontWeight="Light" |
||||
ToolTip.Tip="This will also be the folder name" |
||||
Content="{x:Static lang:Resources.Label_DisplayName}" /> |
||||
<TextBox MinWidth="250" |
||||
Margin="8,0" |
||||
FontSize="16" |
||||
FontWeight="SemiLight" |
||||
VerticalAlignment="Stretch" |
||||
VerticalContentAlignment="Center" |
||||
ToolTip.Tip="This will also be the folder name" |
||||
Text="{Binding InstallName, Mode=TwoWay}" /> |
||||
<Label Margin="8,0" |
||||
Content="{Binding FullInstallPath}" Foreground="LightGray" /> |
||||
|
||||
<StackPanel Orientation="Horizontal" |
||||
Margin="8,8,8,8" |
||||
IsVisible="{Binding ShowDuplicateWarning}"> |
||||
<avalonia:SymbolIcon |
||||
Foreground="{DynamicResource ThemeRedColor}" |
||||
Margin="0,0,8,0" |
||||
Symbol="Alert" /> |
||||
<TextBlock |
||||
Foreground="{DynamicResource ThemeRedColor}" |
||||
TextAlignment="Left" |
||||
TextWrapping="Wrap"> |
||||
<Run Text="{x:Static lang:Resources.Label_InstallationWithThisNameExists}" /> |
||||
<LineBreak /> |
||||
<Run Text="{x:Static lang:Resources.Label_PleaseChooseDifferentName}" /> |
||||
</TextBlock> |
||||
</StackPanel> |
||||
|
||||
<Expander Header="Extensions" |
||||
FontSize="16" |
||||
HorizontalAlignment="Stretch" |
||||
IsVisible="{Binding ShowExtensions}" |
||||
Margin="8"> |
||||
<ItemsRepeater ItemsSource="{Binding AvailableExtensions}"> |
||||
<ItemsRepeater.Layout> |
||||
<UniformGridLayout MinColumnSpacing="4" MinRowSpacing="4"/> |
||||
</ItemsRepeater.Layout> |
||||
<ItemsRepeater.ItemTemplate> |
||||
<DataTemplate x:DataType="{x:Type viewModels:ExtensionViewModel}"> |
||||
<CheckBox IsChecked="{Binding IsSelected, Mode=TwoWay}" |
||||
Content="{Binding Extension.DisplayName}"/> |
||||
</DataTemplate> |
||||
</ItemsRepeater.ItemTemplate> |
||||
</ItemsRepeater> |
||||
</Expander> |
||||
|
||||
<Expander Header="{x:Static lang:Resources.Label_AdvancedOptions}" |
||||
FontSize="16" |
||||
HorizontalAlignment="Stretch" |
||||
Margin="8"> |
||||
<Grid ColumnDefinitions="*, *, *" |
||||
RowDefinitions="Auto, Auto" |
||||
Margin="8,0"> |
||||
|
||||
<Label Grid.Row="0" Grid.Column="0" |
||||
Content="{x:Static lang:Resources.Label_SharedModelFolderStrategy}" |
||||
Margin="0,0,0,4" /> |
||||
<controls1:FAComboBox Grid.Row="1" Grid.Column="0" |
||||
ItemsSource="{Binding SelectedPackage.AvailableSharedFolderMethods}" |
||||
MinWidth="150" |
||||
MinHeight="38" |
||||
SelectedItem="{Binding SelectedSharedFolderMethod}"> |
||||
<controls1:FAComboBox.ItemTemplate> |
||||
<DataTemplate DataType="{x:Type models:SharedFolderMethod}"> |
||||
<TextBlock |
||||
Margin="8,4,0,4" |
||||
Text="{Binding }" /> |
||||
</DataTemplate> |
||||
</controls1:FAComboBox.ItemTemplate> |
||||
</controls1:FAComboBox> |
||||
|
||||
<Label Grid.Row="0" Grid.Column="1" |
||||
Content="{x:Static lang:Resources.Label_PyTorchVersion}" |
||||
IsVisible="{Binding ShowTorchVersionOptions}" |
||||
Margin="0,0,0,4" /> |
||||
<controls1:FAComboBox Grid.Row="1" Grid.Column="1" |
||||
ItemsSource="{Binding SelectedPackage.AvailableTorchVersions}" |
||||
MinWidth="150" |
||||
MinHeight="38" |
||||
IsVisible="{Binding ShowTorchVersionOptions}" |
||||
SelectedItem="{Binding SelectedTorchVersion}"> |
||||
<controls1:FAComboBox.ItemTemplate> |
||||
<DataTemplate DataType="{x:Type models:TorchVersion}"> |
||||
<TextBlock |
||||
Margin="8,4,0,4" |
||||
Text="{Binding }" /> |
||||
</DataTemplate> |
||||
</controls1:FAComboBox.ItemTemplate> |
||||
</controls1:FAComboBox> |
||||
|
||||
<Label Grid.Row="0" Grid.Column="2" |
||||
Content="{x:Static lang:Resources.Label_Commit}" |
||||
Margin="0,0,0,4" |
||||
IsVisible="{Binding !IsReleaseMode}" /> |
||||
<controls1:FAComboBox Grid.Row="1" Grid.Column="2" |
||||
IsVisible="{Binding !IsReleaseMode}" |
||||
ItemsSource="{Binding AvailableCommits}" |
||||
MinWidth="150" |
||||
MinHeight="38" |
||||
SelectedItem="{Binding SelectedCommit}"> |
||||
<controls1:FAComboBox.ItemTemplate> |
||||
<DataTemplate DataType="{x:Type database:GitCommit}"> |
||||
<TextBlock |
||||
Margin="8,4,0,4" |
||||
Name="NameTextBlock" |
||||
Text="{Binding ShortSha}" /> |
||||
</DataTemplate> |
||||
</controls1:FAComboBox.ItemTemplate> |
||||
</controls1:FAComboBox> |
||||
</Grid> |
||||
</Expander> |
||||
|
||||
<Button Classes="success" |
||||
Margin="8,8,8,8" |
||||
HorizontalAlignment="Stretch" |
||||
VerticalAlignment="Stretch" |
||||
FontSize="16" |
||||
Command="{Binding InstallCommand}" |
||||
Content="{x:Static lang:Resources.Action_Install}" /> |
||||
|
||||
</StackPanel> |
||||
</Grid> |
||||
|
||||
</controls:UserControlBase> |
@ -0,0 +1,13 @@
|
||||
using StabilityMatrix.Avalonia.Controls; |
||||
using StabilityMatrix.Core.Attributes; |
||||
|
||||
namespace StabilityMatrix.Avalonia.Views; |
||||
|
||||
[Transient] |
||||
public partial class PackageInstallDetailView : UserControlBase |
||||
{ |
||||
public PackageInstallDetailView() |
||||
{ |
||||
InitializeComponent(); |
||||
} |
||||
} |
@ -0,0 +1,15 @@
|
||||
using StabilityMatrix.Core.Models.FileInterfaces; |
||||
using StabilityMatrix.Core.Models.Packages.Extensions; |
||||
using StabilityMatrix.Core.Models.Progress; |
||||
|
||||
namespace StabilityMatrix.Core.Models.PackageModification; |
||||
|
||||
public class InstallExtensionStep(ExtensionBase extension, DirectoryPath extensionsDir) : IPackageStep |
||||
{ |
||||
public Task ExecuteAsync(IProgress<ProgressReport>? progress = null) |
||||
{ |
||||
return extension.InstallExtensionAsync(extensionsDir, extension.MainBranch); |
||||
} |
||||
|
||||
public string ProgressTitle => $"Installing {extension.DisplayName}"; |
||||
} |
@ -0,0 +1,7 @@
|
||||
namespace StabilityMatrix.Core.Models; |
||||
|
||||
public enum PackageType |
||||
{ |
||||
SdInference, |
||||
SdTraining |
||||
} |
@ -0,0 +1,28 @@
|
||||
using StabilityMatrix.Core.Helper; |
||||
using StabilityMatrix.Core.Models.FileInterfaces; |
||||
|
||||
namespace StabilityMatrix.Core.Models.Packages.Extensions; |
||||
|
||||
public class ComfyManager(IPrerequisiteHelper prerequisiteHelper) : ExtensionBase |
||||
{ |
||||
public override string RepoName => "ComfyUI-Manager"; |
||||
public override string DisplayName { get; set; } = "ComfyUI Manager"; |
||||
public override string Author => "ltdrdata"; |
||||
|
||||
public override string Blurb => |
||||
"ComfyUI-Manager is an extension designed to enhance the usability of ComfyUI. It offers management functions to install, remove, disable, and enable various custom nodes of ComfyUI."; |
||||
|
||||
public override IEnumerable<string> CompatibleWith => [nameof(ComfyUI)]; |
||||
public override string MainBranch => "main"; |
||||
|
||||
public override Task InstallExtensionAsync( |
||||
DirectoryPath installDirectory, |
||||
string branch, |
||||
CancellationToken cancellationToken = default |
||||
) |
||||
{ |
||||
return Directory.Exists(Path.Combine(installDirectory, RepoName)) |
||||
? Task.CompletedTask |
||||
: prerequisiteHelper.RunGit(new[] { "clone", GithubUrl }, installDirectory); |
||||
} |
||||
} |
@ -0,0 +1,24 @@
|
||||
using StabilityMatrix.Core.Models.FileInterfaces; |
||||
|
||||
namespace StabilityMatrix.Core.Models.Packages.Extensions; |
||||
|
||||
public abstract class ExtensionBase |
||||
{ |
||||
public string ByAuthor => $"By {Author}"; |
||||
|
||||
public abstract string RepoName { get; } |
||||
public abstract string DisplayName { get; set; } |
||||
public abstract string Author { get; } |
||||
|
||||
public abstract string Blurb { get; } |
||||
public abstract IEnumerable<string> CompatibleWith { get; } |
||||
public abstract string MainBranch { get; } |
||||
|
||||
public abstract Task InstallExtensionAsync( |
||||
DirectoryPath installDirectory, |
||||
string branch, |
||||
CancellationToken cancellationToken = default |
||||
); |
||||
|
||||
public string GithubUrl => $"https://github.com/{Author}/{RepoName}"; |
||||
} |
Loading…
Reference in new issue