Browse Source

finished up install stuff, added to download/progressmanager, restore dialog, etc

pull/117/head
JT 1 year ago
parent
commit
aefef59546
  1. 4
      StabilityMatrix.Avalonia/App.axaml.cs
  2. 7
      StabilityMatrix.Avalonia/DesignData/DesignData.cs
  3. 11
      StabilityMatrix.Avalonia/ViewModels/Base/ConsoleProgressViewModel.cs
  4. 2
      StabilityMatrix.Avalonia/ViewModels/Base/ContentDialogProgressViewModelBase.cs
  5. 13
      StabilityMatrix.Avalonia/ViewModels/Base/ProgressItemViewModelBase.cs
  6. 3
      StabilityMatrix.Avalonia/ViewModels/Dialogs/InstallerViewModel.cs
  7. 25
      StabilityMatrix.Avalonia/ViewModels/Dialogs/PackageModificationDialogViewModel.cs
  8. 28
      StabilityMatrix.Avalonia/ViewModels/MainWindowViewModel.cs
  9. 7
      StabilityMatrix.Avalonia/ViewModels/PackageManagerViewModel.cs
  10. 2
      StabilityMatrix.Avalonia/ViewModels/Progress/DownloadProgressItemViewModel.cs
  11. 75
      StabilityMatrix.Avalonia/ViewModels/Progress/PackageInstallProgressItemViewModel.cs
  12. 6
      StabilityMatrix.Avalonia/ViewModels/Progress/ProgressItemViewModel.cs
  13. 25
      StabilityMatrix.Avalonia/ViewModels/Progress/ProgressManagerViewModel.cs
  14. 22
      StabilityMatrix.Avalonia/Views/Dialogs/PackageModificationDialog.axaml
  15. 3
      StabilityMatrix.Avalonia/Views/MainWindow.axaml
  16. 7
      StabilityMatrix.Avalonia/Views/MainWindow.axaml.cs
  17. 69
      StabilityMatrix.Avalonia/Views/ProgressManagerPage.axaml
  18. 40
      StabilityMatrix.Core/Helper/EventManager.cs
  19. 7
      StabilityMatrix.Core/Models/PackageModification/AddInstalledPackageStep.cs
  20. 2
      StabilityMatrix.Core/Models/PackageModification/IPackageModificationRunner.cs
  21. 13
      StabilityMatrix.Core/Models/PackageModification/PackageModificationRunner.cs
  22. 24
      StabilityMatrix.Core/Models/PackageModification/SetPackageInstallingStep.cs
  23. 6
      StabilityMatrix.Core/Models/Packages/VladAutomatic.cs
  24. 7
      StabilityMatrix.Core/Models/Progress/ProgressItem.cs
  25. 1
      StabilityMatrix.Core/Services/ISettingsManager.cs
  26. 1
      StabilityMatrix.Core/Services/SettingsManager.cs

4
StabilityMatrix.Avalonia/App.axaml.cs

@ -47,6 +47,7 @@ using StabilityMatrix.Avalonia.ViewModels.CheckpointBrowser;
using StabilityMatrix.Avalonia.ViewModels.CheckpointManager;
using StabilityMatrix.Avalonia.ViewModels.Dialogs;
using StabilityMatrix.Avalonia.ViewModels.PackageManager;
using StabilityMatrix.Avalonia.ViewModels.Progress;
using StabilityMatrix.Avalonia.Views;
using StabilityMatrix.Avalonia.Views.Dialogs;
using StabilityMatrix.Core.Api;
@ -346,7 +347,6 @@ public sealed class App : Application
services.AddSingleton<BasePackage, VoltaML>();
services.AddSingleton<BasePackage, InvokeAI>();
services.AddSingleton<BasePackage, Fooocus>();
//services.AddSingleton<BasePackage, KohyaSs>();
}
private static IServiceCollection ConfigureServices()
@ -372,7 +372,7 @@ public sealed class App : Application
services.AddSingleton<IUpdateHelper, UpdateHelper>();
services.AddSingleton<INavigationService, NavigationService>();
services.AddSingleton<IModelIndexService, ModelIndexService>();
services.AddSingleton<IPackageModificationRunner, PackageModificationRunner>();
services.AddTransient<IPackageModificationRunner, PackageModificationRunner>();
services.AddSingleton<ITrackedDownloadService, TrackedDownloadService>();
services.AddSingleton<IDisposable>(

7
StabilityMatrix.Avalonia/DesignData/DesignData.cs

@ -13,6 +13,7 @@ using StabilityMatrix.Avalonia.ViewModels.Base;
using StabilityMatrix.Avalonia.ViewModels.CheckpointBrowser;
using StabilityMatrix.Avalonia.ViewModels.CheckpointManager;
using StabilityMatrix.Avalonia.ViewModels.Dialogs;
using StabilityMatrix.Avalonia.ViewModels.Progress;
using StabilityMatrix.Core.Api;
using StabilityMatrix.Core.Database;
using StabilityMatrix.Core.Helper;
@ -276,6 +277,12 @@ public static class DesignData
)
),
new MockDownloadProgressItemViewModel("Test File 2.exe"),
new PackageInstallProgressItemViewModel(
new PackageModificationRunner
{
CurrentProgress = new ProgressReport(0.5f, "Installing package...")
}
)
}
);

11
StabilityMatrix.Avalonia/ViewModels/Base/ConsoleProgressViewModel.cs

@ -0,0 +1,11 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace StabilityMatrix.Avalonia.ViewModels.Base;
public partial class ConsoleProgressViewModel : ProgressViewModel
{
public ConsoleViewModel Console { get; } = new();
[ObservableProperty]
private bool closeWhenFinished;
}

2
StabilityMatrix.Avalonia/ViewModels/Base/ContentDialogProgressViewModelBase.cs

@ -3,7 +3,7 @@ using FluentAvalonia.UI.Controls;
namespace StabilityMatrix.Avalonia.ViewModels.Base;
public class ContentDialogProgressViewModelBase : ProgressViewModel
public class ContentDialogProgressViewModelBase : ConsoleProgressViewModel
{
public event EventHandler<ContentDialogResult>? PrimaryButtonClick;
public event EventHandler<ContentDialogResult>? SecondaryButtonClick;

13
StabilityMatrix.Avalonia/ViewModels/Base/ProgressItemViewModelBase.cs

@ -6,11 +6,16 @@ namespace StabilityMatrix.Avalonia.ViewModels.Base;
public abstract partial class ProgressItemViewModelBase : ViewModelBase
{
[ObservableProperty] private Guid id;
[ObservableProperty] private string? name;
[ObservableProperty] private bool failed;
[ObservableProperty]
private Guid id;
[ObservableProperty]
private string? name;
[ObservableProperty]
private bool failed;
public virtual bool IsCompleted => Progress.Value >= 100 || Failed;
public ProgressViewModel Progress { get; } = new();
public ContentDialogProgressViewModelBase Progress { get; } = new();
}

3
StabilityMatrix.Avalonia/ViewModels/Dialogs/InstallerViewModel.cs

@ -215,6 +215,8 @@ public partial class InstallerViewModel : ContentDialogViewModelBase
return Task.CompletedTask;
}
var setPackageInstallingStep = new SetPackageInstallingStep(settingsManager, InstallName);
var installLocation = Path.Combine(settingsManager.LibraryDir, "Packages", InstallName);
var prereqStep = new SetupPrerequisitesStep(prerequisiteHelper, pyRunner);
@ -270,6 +272,7 @@ public partial class InstallerViewModel : ContentDialogViewModelBase
var steps = new List<IPackageStep>
{
setPackageInstallingStep,
prereqStep,
downloadStep,
installStep,

25
StabilityMatrix.Avalonia/ViewModels/Dialogs/PackageModificationDialogViewModel.cs

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Avalonia.Controls.Notifications;
@ -25,27 +26,45 @@ public class PackageModificationDialogViewModel : ContentDialogProgressViewModel
this.packageModificationRunner = packageModificationRunner;
this.notificationService = notificationService;
this.steps = steps;
CloseWhenFinished = true;
}
public ConsoleViewModel Console { get; } = new();
public override async Task OnLoadedAsync()
{
await Console.Clear();
Console.Post(string.Join(Environment.NewLine, packageModificationRunner.ConsoleOutput));
// idk why this is getting called twice
if (!packageModificationRunner.IsRunning)
{
EventManager.Instance.OnPackageInstallProgressAdded(packageModificationRunner);
packageModificationRunner.ProgressChanged += PackageModificationRunnerOnProgressChanged;
await packageModificationRunner.ExecuteSteps(steps.ToList());
var packageName = string.Empty;
var addPackageStep = steps.FirstOrDefault(step => step is AddInstalledPackageStep);
if (addPackageStep != null)
{
addPackageStep
.GetType()
.GetProperty("newInstalledPackage")
?.GetValue(addPackageStep, null);
}
notificationService.Show(
"Package Install Completed",
"Package install completed successfully.",
NotificationType.Success
);
EventManager.Instance.OnInstalledPackagesChanged();
if (CloseWhenFinished)
{
OnCloseButtonClick();
}
}
}
private void PackageModificationRunnerOnProgressChanged(object? sender, ProgressReport e)
{

28
StabilityMatrix.Avalonia/ViewModels/MainWindowViewModel.cs

@ -11,6 +11,7 @@ using StabilityMatrix.Avalonia.Controls;
using StabilityMatrix.Avalonia.Services;
using StabilityMatrix.Avalonia.ViewModels.Base;
using StabilityMatrix.Avalonia.ViewModels.Dialogs;
using StabilityMatrix.Avalonia.ViewModels.Progress;
using StabilityMatrix.Avalonia.Views;
using StabilityMatrix.Avalonia.Views.Dialogs;
using StabilityMatrix.Core.Attributes;
@ -47,7 +48,8 @@ public partial class MainWindowViewModel : ViewModelBase
ISettingsManager settingsManager,
IDiscordRichPresenceService discordRichPresenceService,
ServiceManager<ViewModelBase> dialogFactory,
ITrackedDownloadService trackedDownloadService)
ITrackedDownloadService trackedDownloadService
)
{
this.settingsManager = settingsManager;
this.dialogFactory = dialogFactory;
@ -72,7 +74,8 @@ public partial class MainWindowViewModel : ViewModelBase
await base.OnLoadedAsync();
// Skip if design mode
if (Design.IsDesignMode) return;
if (Design.IsDesignMode)
return;
if (!await EnsureDataDirectory())
{
@ -98,16 +101,14 @@ public partial class MainWindowViewModel : ViewModelBase
IsPrimaryButtonEnabled = false,
IsSecondaryButtonEnabled = false,
IsFooterVisible = false,
Content = new OneClickInstallDialog
{
DataContext = viewModel
},
Content = new OneClickInstallDialog { DataContext = viewModel },
};
EventManager.Instance.OneClickInstallFinished += (_, skipped) =>
{
dialog.Hide();
if (skipped) return;
if (skipped)
return;
EventManager.Instance.OnTeachingTooltipNeeded();
};
@ -125,7 +126,8 @@ public partial class MainWindowViewModel : ViewModelBase
if (!settingsManager.TryFindLibrary())
{
var result = await ShowSelectDataDirectoryDialog();
if (!result) return false;
if (!result)
return false;
}
// Try to find library again, should be found now
@ -155,10 +157,7 @@ public partial class MainWindowViewModel : ViewModelBase
IsPrimaryButtonEnabled = false,
IsSecondaryButtonEnabled = false,
IsFooterVisible = false,
Content = new SelectDataDirectoryDialog
{
DataContext = viewModel
}
Content = new SelectDataDirectoryDialog { DataContext = viewModel }
};
var result = await dialog.ShowAsync();
@ -191,10 +190,7 @@ public partial class MainWindowViewModel : ViewModelBase
IsPrimaryButtonEnabled = false,
IsSecondaryButtonEnabled = false,
IsFooterVisible = false,
Content = new UpdateDialog
{
DataContext = viewModel
}
Content = new UpdateDialog { DataContext = viewModel }
};
await dialog.ShowAsync();

7
StabilityMatrix.Avalonia/ViewModels/PackageManagerViewModel.cs

@ -163,8 +163,6 @@ public partial class PackageManagerViewModel : PageViewModelBase
await dialog.ShowAsync();
}
await OnLoadedAsync();
}
private IEnumerable<UnknownInstalledPackage> IndexUnknownPackages()
@ -192,6 +190,11 @@ public partial class PackageManagerViewModel : PageViewModelBase
continue;
}
if (settingsManager.PackageInstallsInProgress.Contains(subDir.Name))
{
continue;
}
yield return UnknownInstalledPackage.FromDirectoryName(subDir.Name);
}
}

2
StabilityMatrix.Avalonia/ViewModels/DownloadProgressItemViewModel.cs → StabilityMatrix.Avalonia/ViewModels/Progress/DownloadProgressItemViewModel.cs

@ -4,7 +4,7 @@ using StabilityMatrix.Avalonia.ViewModels.Base;
using StabilityMatrix.Core.Models;
using StabilityMatrix.Core.Models.Progress;
namespace StabilityMatrix.Avalonia.ViewModels;
namespace StabilityMatrix.Avalonia.ViewModels.Progress;
public class DownloadProgressItemViewModel : PausableProgressItemViewModelBase
{

75
StabilityMatrix.Avalonia/ViewModels/Progress/PackageInstallProgressItemViewModel.cs

@ -0,0 +1,75 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using FluentAvalonia.UI.Controls;
using StabilityMatrix.Avalonia.Controls;
using StabilityMatrix.Avalonia.ViewModels.Base;
using StabilityMatrix.Avalonia.Views.Dialogs;
using StabilityMatrix.Core.Helper;
using StabilityMatrix.Core.Models.PackageModification;
using StabilityMatrix.Core.Models.Progress;
namespace StabilityMatrix.Avalonia.ViewModels.Progress;
public partial class PackageInstallProgressItemViewModel : ProgressItemViewModelBase
{
private readonly IPackageModificationRunner packageModificationRunner;
private BetterContentDialog? dialog;
public PackageInstallProgressItemViewModel(IPackageModificationRunner packageModificationRunner)
{
this.packageModificationRunner = packageModificationRunner;
Id = packageModificationRunner.Id;
Name = packageModificationRunner.CurrentStep?.ProgressTitle;
Progress.Value = packageModificationRunner.CurrentProgress.Percentage;
Progress.Text = packageModificationRunner.ConsoleOutput.LastOrDefault();
Progress.IsIndeterminate = packageModificationRunner.CurrentProgress.IsIndeterminate;
Progress.Console.Post(
string.Join(Environment.NewLine, packageModificationRunner.ConsoleOutput)
);
packageModificationRunner.ProgressChanged += PackageModificationRunnerOnProgressChanged;
}
private void PackageModificationRunnerOnProgressChanged(object? sender, ProgressReport e)
{
Progress.Value = e.Percentage;
Progress.Text = e.Message;
Progress.IsIndeterminate = e.IsIndeterminate;
Name = packageModificationRunner.CurrentStep?.ProgressTitle;
if (string.IsNullOrWhiteSpace(e.Message) || e.Message.Equals("Downloading..."))
return;
Progress.Console.PostLine(e.Message);
EventManager.Instance.OnScrollToBottomRequested();
if (
e is { Message: not null, Percentage: >= 100 }
&& e.Message.Contains("Package Install Complete")
&& Progress.CloseWhenFinished
)
{
EventManager.Instance.OnInstalledPackagesChanged();
dialog?.Hide();
}
}
public async Task ShowProgressDialog()
{
Progress.CloseWhenFinished = true;
dialog = new BetterContentDialog
{
MaxDialogWidth = 900,
MinDialogWidth = 900,
DefaultButton = ContentDialogButton.Close,
IsPrimaryButtonEnabled = false,
IsSecondaryButtonEnabled = false,
IsFooterVisible = false,
Content = new PackageModificationDialog { DataContext = Progress }
};
EventManager.Instance.OnToggleProgressFlyout();
await dialog.ShowAsync();
}
}

6
StabilityMatrix.Avalonia/ViewModels/ProgressItemViewModel.cs → StabilityMatrix.Avalonia/ViewModels/Progress/ProgressItemViewModel.cs

@ -1,10 +1,8 @@
using System;
using CommunityToolkit.Mvvm.ComponentModel;
using StabilityMatrix.Avalonia.ViewModels.Base;
using StabilityMatrix.Avalonia.ViewModels.Base;
using StabilityMatrix.Core.Helper;
using StabilityMatrix.Core.Models.Progress;
namespace StabilityMatrix.Avalonia.ViewModels;
namespace StabilityMatrix.Avalonia.ViewModels.Progress;
public class ProgressItemViewModel : ProgressItemViewModelBase
{

25
StabilityMatrix.Avalonia/ViewModels/ProgressManagerViewModel.cs → StabilityMatrix.Avalonia/ViewModels/Progress/ProgressManagerViewModel.cs

@ -3,6 +3,7 @@ using System.Linq;
using Avalonia.Collections;
using Avalonia.Controls.Notifications;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using FluentAvalonia.UI.Controls;
using StabilityMatrix.Avalonia.Services;
using StabilityMatrix.Avalonia.ViewModels.Base;
@ -10,12 +11,13 @@ using StabilityMatrix.Avalonia.Views;
using StabilityMatrix.Core.Attributes;
using StabilityMatrix.Core.Helper;
using StabilityMatrix.Core.Models;
using StabilityMatrix.Core.Models.PackageModification;
using StabilityMatrix.Core.Models.Progress;
using StabilityMatrix.Core.Services;
using Symbol = FluentIcons.Common.Symbol;
using SymbolIconSource = FluentIcons.FluentAvalonia.SymbolIconSource;
namespace StabilityMatrix.Avalonia.ViewModels;
namespace StabilityMatrix.Avalonia.ViewModels.Progress;
[View(typeof(ProgressManagerPage))]
public partial class ProgressManagerViewModel : PageViewModelBase
@ -24,9 +26,10 @@ public partial class ProgressManagerViewModel : PageViewModelBase
public override string Title => "Download Manager";
public override IconSource IconSource => new SymbolIconSource {Symbol = Symbol.ArrowCircleDown, IsFilled = true};
public AvaloniaList<ProgressItemViewModelBase> ProgressItems { get; } = new();
[ObservableProperty] private bool isOpen;
public ProgressManagerViewModel(
ITrackedDownloadService trackedDownloadService,
INotificationService notificationService)
@ -35,6 +38,13 @@ public partial class ProgressManagerViewModel : PageViewModelBase
// Attach to the event
trackedDownloadService.DownloadAdded += TrackedDownloadService_OnDownloadAdded;
EventManager.Instance.PackageInstallProgressAdded += InstanceOnPackageInstallProgressAdded;
EventManager.Instance.ToggleProgressFlyout += (_, _) => IsOpen = !IsOpen;
}
private void InstanceOnPackageInstallProgressAdded(object? sender, IPackageModificationRunner runner)
{
AddPackageInstall(runner);
}
private void TrackedDownloadService_OnDownloadAdded(object? sender, TrackedDownload e)
@ -90,6 +100,17 @@ public partial class ProgressManagerViewModel : PageViewModelBase
}
}
private void AddPackageInstall(IPackageModificationRunner packageModificationRunner)
{
if (ProgressItems.Any(vm => vm.Id == packageModificationRunner.Id))
{
return;
}
var vm = new PackageInstallProgressItemViewModel(packageModificationRunner);
ProgressItems.Add(vm);
}
private void ShowFailedNotification(string title, string message)
{
notificationService.ShowPersistent(title, message, NotificationType.Error);

22
StabilityMatrix.Avalonia/Views/Dialogs/PackageModificationDialog.axaml

@ -5,10 +5,11 @@
xmlns:controls="clr-namespace:StabilityMatrix.Avalonia.Controls"
xmlns:dialogs="clr-namespace:StabilityMatrix.Avalonia.ViewModels.Dialogs"
xmlns:avaloniaEdit="https://github.com/avaloniaui/avaloniaedit"
xmlns:base="clr-namespace:StabilityMatrix.Avalonia.ViewModels.Base"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:DataType="dialogs:PackageModificationDialogViewModel"
x:DataType="base:ContentDialogProgressViewModelBase"
x:Class="StabilityMatrix.Avalonia.Views.Dialogs.PackageModificationDialog">
<Grid Margin="8" RowDefinitions="Auto, Auto, Auto, *">
<Grid Margin="8" RowDefinitions="Auto, Auto, Auto, *, Auto, Auto">
<TextBlock Grid.Row="0" Text="{Binding Text}"
FontSize="16"
TextAlignment="Center"
@ -17,16 +18,19 @@
<TextBlock Grid.Row="1" Text="{Binding Description}"
Margin="4"
TextWrapping="WrapWithOverflow"
TextAlignment="Center"
IsVisible="{Binding !#Expander.IsExpanded}"/>
<ProgressBar Grid.Row="2" Value="{Binding Value}"
Margin="8"
IsIndeterminate="{Binding IsIndeterminate}"/>
<Expander Grid.Row="3" Header="More Details" x:Name="Expander">
<Expander Grid.Row="3"
Margin="8"
Header="More Details" x:Name="Expander">
<avaloniaEdit:TextEditor
x:Name="Console"
Margin="8,8,16,10"
Margin="8"
MaxHeight="400"
DataContext="{Binding Console}"
Document="{Binding Document}"
@ -37,5 +41,15 @@
VerticalScrollBarVisibility="Auto"
WordWrap="True" />
</Expander>
<CheckBox Grid.Row="4" IsChecked="{Binding CloseWhenFinished}"
HorizontalAlignment="Center"
Margin="4" Content="Close dialog when finished"/>
<Button Grid.Row="5" Content="Close"
FontSize="20"
Margin="8"
HorizontalAlignment="Center"
Command="{Binding OnCloseButtonClick}"/>
</Grid>
</controls:UserControlBase>

3
StabilityMatrix.Avalonia/Views/MainWindow.axaml

@ -16,7 +16,6 @@
Width="1100"
Height="750"
Title="Stability Matrix"
FontFamily="San Francisco, Segoe UI, Helvetica Neue, Helvetica, Arial, sans-serif"
x:Class="StabilityMatrix.Avalonia.Views.MainWindow">
<Grid RowDefinitions="Auto,Auto,*">
@ -119,7 +118,7 @@
<controls:BetterFlyout Placement="RightEdgeAlignedBottom"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Auto"
Content="{Binding }" />
Content="{Binding }"/>
</ui:NavigationViewItem.ContextFlyout>
<ui:NavigationViewItem.InfoBadge>
<ui:InfoBadge Value="{Binding ProgressItems.Count}"

7
StabilityMatrix.Avalonia/Views/MainWindow.axaml.cs

@ -25,6 +25,7 @@ using StabilityMatrix.Avalonia.Controls;
using StabilityMatrix.Avalonia.Services;
using StabilityMatrix.Avalonia.ViewModels;
using StabilityMatrix.Avalonia.ViewModels.Base;
using StabilityMatrix.Core.Helper;
using StabilityMatrix.Core.Processes;
#if DEBUG
using StabilityMatrix.Avalonia.Diagnostics.Views;
@ -38,6 +39,8 @@ public partial class MainWindow : AppWindowBase
private readonly INotificationService notificationService;
private readonly INavigationService navigationService;
private FlyoutBase? progressFlyout;
[DesignOnly(true)]
[SuppressMessage("ReSharper", "UnusedMember.Global")]
public MainWindow()
@ -62,6 +65,8 @@ public partial class MainWindow : AppWindowBase
#endif
TitleBar.ExtendsContentIntoTitleBar = true;
TitleBar.TitleBarHitTestType = TitleBarHitTestType.Complex;
EventManager.Instance.ToggleProgressFlyout += (_, _) => progressFlyout?.Hide();
}
/// <inheritdoc />
@ -231,6 +236,8 @@ public partial class MainWindow : AppWindowBase
var item = sender as NavigationViewItem;
var flyout = item!.ContextFlyout;
flyout!.ShowAt(item);
progressFlyout = flyout;
}
private void FooterUpdateItem_OnTapped(object? sender, TappedEventArgs e)

69
StabilityMatrix.Avalonia/Views/ProgressManagerPage.axaml

@ -11,11 +11,12 @@
xmlns:ui="using:FluentAvalonia.UI.Controls"
xmlns:vm="clr-namespace:StabilityMatrix.Avalonia.ViewModels"
xmlns:vmBase="clr-namespace:StabilityMatrix.Avalonia.ViewModels.Base"
xmlns:progress="clr-namespace:StabilityMatrix.Avalonia.ViewModels.Progress"
MaxHeight="250"
d:DataContext="{x:Static mocks:DesignData.ProgressManagerViewModel}"
d:DesignHeight="250"
d:DesignWidth="300"
x:DataType="vm:ProgressManagerViewModel"
x:DataType="progress:ProgressManagerViewModel"
mc:Ignorable="d">
<ScrollViewer>
<Grid RowDefinitions="Auto, *">
@ -117,7 +118,7 @@
</Border>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:ProgressItemViewModel}">
<DataTemplate DataType="{x:Type progress:ProgressItemViewModel}">
<Border
Margin="4"
Padding="8"
@ -164,6 +165,70 @@
</Grid>
</Border>
</DataTemplate>
<DataTemplate DataType="{x:Type progress:PackageInstallProgressItemViewModel}">
<Border
Margin="4"
Padding="8"
Background="#22000000"
BorderBrush="#33000000"
BorderThickness="2"
CornerRadius="8">
<Grid ColumnDefinitions="*,Auto" RowDefinitions="*,Auto">
<StackPanel Grid.Row="0" Grid.Column="0">
<TextBlock Margin="0,0"
Text="{Binding Name, Mode=OneWay}" />
<!-- non-indeterminate progress -->
<TextBlock
Margin="0,4"
MaxWidth="300"
IsVisible="{Binding !Progress.IsIndeterminate}">
<Run Text="{Binding Progress.Text, Mode=OneWay}" />
<Run Text="{Binding Progress.Value, Mode=OneWay}" /><Run Text="%" />
</TextBlock>
<!-- indeterminate progress -->
<TextBlock
Margin="0,4"
MaxWidth="300"
IsVisible="{Binding Progress.IsIndeterminate}"
Text="{Binding Progress.Text, Mode=OneWay}" />
</StackPanel>
<!-- Buttons -->
<Button
Grid.Row="0"
Grid.Column="1"
Margin="8,0"
ToolTip.Tip="Show Progress Dialog"
Command="{Binding ShowProgressDialog}"
Classes="transparent-full">
<ui:SymbolIcon Symbol="Open" />
</Button>
<ProgressBar
Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="2"
Margin="0,8,0,4"
IsIndeterminate="{Binding Progress.IsIndeterminate}"
Value="{Binding Progress.Value, Mode=OneWay}">
<ProgressBar.Transitions>
<Transitions>
<DoubleTransition Property="Value" Duration="00:00:00.150">
<DoubleTransition.Easing>
<SineEaseInOut />
</DoubleTransition.Easing>
</DoubleTransition>
</Transitions>
</ProgressBar.Transitions>
</ProgressBar>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.DataTemplates>
</ItemsControl>
</Grid>

40
StabilityMatrix.Core/Helper/EventManager.cs

@ -1,4 +1,5 @@
using StabilityMatrix.Core.Models;
using StabilityMatrix.Core.Models.PackageModification;
using StabilityMatrix.Core.Models.Progress;
using StabilityMatrix.Core.Models.Update;
@ -10,10 +11,7 @@ public class EventManager
{
public static EventManager Instance { get; } = new();
private EventManager()
{
}
private EventManager() { }
public event EventHandler<int>? GlobalProgressChanged;
public event EventHandler? InstalledPackagesChanged;
@ -26,18 +24,40 @@ public class EventManager
public event EventHandler<ProgressItem>? ProgressChanged;
public event EventHandler<RunningPackageStatusChangedEventArgs>? RunningPackageStatusChanged;
public void OnGlobalProgressChanged(int progress) => GlobalProgressChanged?.Invoke(this, progress);
public void OnInstalledPackagesChanged() => InstalledPackagesChanged?.Invoke(this, EventArgs.Empty);
public void OnOneClickInstallFinished(bool skipped) => OneClickInstallFinished?.Invoke(this, skipped);
public event EventHandler<IPackageModificationRunner>? PackageInstallProgressAdded;
public event EventHandler? ToggleProgressFlyout;
public void OnGlobalProgressChanged(int progress) =>
GlobalProgressChanged?.Invoke(this, progress);
public void OnInstalledPackagesChanged() =>
InstalledPackagesChanged?.Invoke(this, EventArgs.Empty);
public void OnOneClickInstallFinished(bool skipped) =>
OneClickInstallFinished?.Invoke(this, skipped);
public void OnTeachingTooltipNeeded() => TeachingTooltipNeeded?.Invoke(this, EventArgs.Empty);
public void OnDevModeSettingChanged(bool value) => DevModeSettingChanged?.Invoke(this, value);
public void OnUpdateAvailable(UpdateInfo args) => UpdateAvailable?.Invoke(this, args);
public void OnPackageLaunchRequested(Guid packageId) =>
PackageLaunchRequested?.Invoke(this, packageId);
public void OnScrollToBottomRequested() =>
ScrollToBottomRequested?.Invoke(this, EventArgs.Empty);
public void OnProgressChanged(ProgressItem progress) =>
ProgressChanged?.Invoke(this, progress);
public void OnProgressChanged(ProgressItem progress) => ProgressChanged?.Invoke(this, progress);
public void OnRunningPackageStatusChanged(PackagePair? currentPackagePair) =>
RunningPackageStatusChanged?.Invoke(this, new RunningPackageStatusChangedEventArgs(currentPackagePair));
RunningPackageStatusChanged?.Invoke(
this,
new RunningPackageStatusChangedEventArgs(currentPackagePair)
);
public void OnPackageInstallProgressAdded(IPackageModificationRunner runner) =>
PackageInstallProgressAdded?.Invoke(this, runner);
public void OnToggleProgressFlyout() => ToggleProgressFlyout?.Invoke(this, EventArgs.Empty);
}

7
StabilityMatrix.Core/Models/PackageModification/AddInstalledPackageStep.cs

@ -19,10 +19,15 @@ public class AddInstalledPackageStep : IPackageStep
public async Task ExecuteAsync(IProgress<ProgressReport>? progress = null)
{
if (!string.IsNullOrWhiteSpace(newInstalledPackage.DisplayName))
{
settingsManager.PackageInstallsInProgress.Remove(newInstalledPackage.DisplayName);
}
await using var transaction = settingsManager.BeginTransaction();
transaction.Settings.InstalledPackages.Add(newInstalledPackage);
transaction.Settings.ActiveInstalledPackageId = newInstalledPackage.Id;
}
public string ProgressTitle => "Finishing up...";
public string ProgressTitle => $"{newInstalledPackage.DisplayName} Installed";
}

2
StabilityMatrix.Core/Models/PackageModification/IPackageModificationRunner.cs

@ -9,4 +9,6 @@ public interface IPackageModificationRunner
ProgressReport CurrentProgress { get; set; }
IPackageStep? CurrentStep { get; set; }
event EventHandler<ProgressReport>? ProgressChanged;
List<string> ConsoleOutput { get; }
Guid Id { get; }
}

13
StabilityMatrix.Core/Models/PackageModification/PackageModificationRunner.cs

@ -6,9 +6,14 @@ public class PackageModificationRunner : IPackageModificationRunner
{
public async Task ExecuteSteps(IReadOnlyList<IPackageStep> steps)
{
var progress = new Progress<ProgressReport>(report =>
IProgress<ProgressReport> progress = new Progress<ProgressReport>(report =>
{
CurrentProgress = report;
if (!string.IsNullOrWhiteSpace(report.Message))
{
ConsoleOutput.Add(report.Message);
}
OnProgressChanged(report);
});
@ -19,12 +24,18 @@ public class PackageModificationRunner : IPackageModificationRunner
await step.ExecuteAsync(progress).ConfigureAwait(false);
}
progress.Report(
new ProgressReport(1f, message: "Package Install Complete", isIndeterminate: false)
);
IsRunning = false;
}
public bool IsRunning { get; set; }
public ProgressReport CurrentProgress { get; set; }
public IPackageStep? CurrentStep { get; set; }
public List<string> ConsoleOutput { get; } = new();
public Guid Id { get; } = Guid.NewGuid();
public event EventHandler<ProgressReport>? ProgressChanged;

24
StabilityMatrix.Core/Models/PackageModification/SetPackageInstallingStep.cs

@ -0,0 +1,24 @@
using StabilityMatrix.Core.Models.Progress;
using StabilityMatrix.Core.Services;
namespace StabilityMatrix.Core.Models.PackageModification;
public class SetPackageInstallingStep : IPackageStep
{
private readonly ISettingsManager settingsManager;
private readonly string packageName;
public SetPackageInstallingStep(ISettingsManager settingsManager, string packageName)
{
this.settingsManager = settingsManager;
this.packageName = packageName;
}
public Task ExecuteAsync(IProgress<ProgressReport>? progress = null)
{
settingsManager.PackageInstallsInProgress.Add(packageName);
return Task.CompletedTask;
}
public string ProgressTitle => "Starting Package Installation";
}

6
StabilityMatrix.Core/Models/Packages/VladAutomatic.cs

@ -101,6 +101,12 @@ public class VladAutomatic : BaseGitPackage
Options = new() { "--lowvram", "--medvram" }
},
new()
{
Name = "Auto-Launch Web UI",
Type = LaunchOptionType.Bool,
Options = new() { "--autolaunch" }
},
new()
{
Name = "Force use of Intel OneAPI XPU backend",
Type = LaunchOptionType.Bool,

7
StabilityMatrix.Core/Models/Progress/ProgressItem.cs

@ -1,3 +1,8 @@
namespace StabilityMatrix.Core.Models.Progress;
public record ProgressItem(Guid ProgressId, string Name, ProgressReport Progress, bool Failed = false);
public record ProgressItem(
Guid ProgressId,
string Name,
ProgressReport Progress,
bool Failed = false
);

1
StabilityMatrix.Core/Services/ISettingsManager.cs

@ -15,6 +15,7 @@ public interface ISettingsManager
string ModelsDirectory { get; }
string DownloadsDirectory { get; }
Settings Settings { get; }
List<string> PackageInstallsInProgress { get; set; }
event EventHandler<string>? LibraryDirChanged;
event EventHandler<PropertyChangedEventArgs>? SettingsPropertyChanged;

1
StabilityMatrix.Core/Services/SettingsManager.cs

@ -56,6 +56,7 @@ public class SettingsManager : ISettingsManager
private string SettingsPath => Path.Combine(LibraryDir, "settings.json");
public string ModelsDirectory => Path.Combine(LibraryDir, "Models");
public string DownloadsDirectory => Path.Combine(LibraryDir, ".downloads");
public List<string> PackageInstallsInProgress { get; set; } = new();
public Settings Settings { get; private set; } = new();

Loading…
Cancel
Save