You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
7.2 KiB
190 lines
7.2 KiB
using System; |
|
using System.Collections.ObjectModel; |
|
using System.Threading.Tasks; |
|
using CommunityToolkit.Mvvm.ComponentModel; |
|
using CommunityToolkit.Mvvm.Input; |
|
using Microsoft.Extensions.Logging; |
|
using StabilityMatrix.Core.Helper; |
|
using StabilityMatrix.Core.Helper.Factory; |
|
using StabilityMatrix.Core.Models; |
|
using StabilityMatrix.Core.Models.Packages; |
|
using StabilityMatrix.Core.Models.Progress; |
|
using StabilityMatrix.Core.Python; |
|
using StabilityMatrix.Core.Services; |
|
|
|
namespace StabilityMatrix.Avalonia.ViewModels.Dialogs; |
|
|
|
public partial class OneClickInstallViewModel : ViewModelBase |
|
{ |
|
private readonly ISettingsManager settingsManager; |
|
private readonly IPackageFactory packageFactory; |
|
private readonly IPrerequisiteHelper prerequisiteHelper; |
|
private readonly ILogger<OneClickInstallViewModel> logger; |
|
private readonly IPyRunner pyRunner; |
|
private readonly ISharedFolders sharedFolders; |
|
private const string DefaultPackageName = "stable-diffusion-webui"; |
|
|
|
[ObservableProperty] private string headerText; |
|
[ObservableProperty] private string subHeaderText; |
|
[ObservableProperty] private string subSubHeaderText = string.Empty; |
|
[ObservableProperty] private bool showInstallButton; |
|
[ObservableProperty] private bool isIndeterminate; |
|
[ObservableProperty] private ObservableCollection<BasePackage> allPackages; |
|
[ObservableProperty] private BasePackage selectedPackage; |
|
|
|
[ObservableProperty] |
|
[NotifyPropertyChangedFor(nameof(IsProgressBarVisible))] |
|
private int oneClickInstallProgress; |
|
|
|
public bool IsProgressBarVisible => OneClickInstallProgress > 0 || IsIndeterminate; |
|
|
|
public OneClickInstallViewModel(ISettingsManager settingsManager, IPackageFactory packageFactory, |
|
IPrerequisiteHelper prerequisiteHelper, ILogger<OneClickInstallViewModel> logger, IPyRunner pyRunner, |
|
ISharedFolders sharedFolders) |
|
{ |
|
this.settingsManager = settingsManager; |
|
this.packageFactory = packageFactory; |
|
this.prerequisiteHelper = prerequisiteHelper; |
|
this.logger = logger; |
|
this.pyRunner = pyRunner; |
|
this.sharedFolders = sharedFolders; |
|
|
|
HeaderText = "Welcome to Stability Matrix!"; |
|
SubHeaderText = "Choose your preferred interface and click Install to get started!"; |
|
ShowInstallButton = true; |
|
AllPackages = |
|
new ObservableCollection<BasePackage>(this.packageFactory.GetAllAvailablePackages()); |
|
SelectedPackage = AllPackages[0]; |
|
} |
|
|
|
[RelayCommand] |
|
private async Task Install() |
|
{ |
|
ShowInstallButton = false; |
|
await DoInstall(); |
|
ShowInstallButton = true; |
|
} |
|
|
|
[RelayCommand] |
|
private Task ToggleAdvancedMode() |
|
{ |
|
EventManager.Instance.OnOneClickInstallFinished(true); |
|
return Task.CompletedTask; |
|
} |
|
|
|
private async Task DoInstall() |
|
{ |
|
HeaderText = $"Installing {SelectedPackage.DisplayName}..."; |
|
|
|
var progressHandler = new Progress<ProgressReport>(progress => |
|
{ |
|
if (progress.Message != null && progress.Message.Contains("Downloading")) |
|
{ |
|
SubHeaderText = $"Downloading prerequisites... {progress.Percentage:N0}%"; |
|
} |
|
else if (progress.Type == ProgressType.Extract) |
|
{ |
|
SubHeaderText = $"Installing git... {progress.Percentage:N0}%"; |
|
} |
|
else if (progress.Title != null && progress.Title.Contains("Unpacking")) |
|
{ |
|
SubHeaderText = $"Unpacking resources... {progress.Percentage:N0}%"; |
|
} |
|
else if (progress.Message != null) |
|
{ |
|
SubHeaderText = progress.Message; |
|
} |
|
|
|
IsIndeterminate = progress.IsIndeterminate; |
|
OneClickInstallProgress = Convert.ToInt32(progress.Percentage); |
|
}); |
|
|
|
await prerequisiteHelper.InstallAllIfNecessary(progressHandler); |
|
|
|
SubHeaderText = "Installing prerequisites..."; |
|
IsIndeterminate = true; |
|
if (!PyRunner.PipInstalled) |
|
{ |
|
await pyRunner.SetupPip(); |
|
} |
|
|
|
if (!PyRunner.VenvInstalled) |
|
{ |
|
await pyRunner.InstallPackage("virtualenv"); |
|
} |
|
IsIndeterminate = false; |
|
|
|
// get latest version & download & install |
|
SubHeaderText = "Getting latest version..."; |
|
var latestVersion = await SelectedPackage.GetLatestVersion(); |
|
SelectedPackage.InstallLocation = |
|
$"{settingsManager.LibraryDir}\\Packages\\{SelectedPackage.Name}"; |
|
SelectedPackage.ConsoleOutput += (_, output) => SubSubHeaderText = output.Text; |
|
|
|
await DownloadPackage(latestVersion); |
|
await InstallPackage(); |
|
|
|
SubHeaderText = "Setting up shared folder links..."; |
|
sharedFolders.SetupLinksForPackage(SelectedPackage, SelectedPackage.InstallLocation); |
|
|
|
var installedPackage = new InstalledPackage |
|
{ |
|
DisplayName = SelectedPackage.DisplayName, |
|
LibraryPath = $"Packages\\{SelectedPackage.Name}", |
|
Id = Guid.NewGuid(), |
|
PackageName = SelectedPackage.Name, |
|
PackageVersion = latestVersion, |
|
DisplayVersion = latestVersion, |
|
LaunchCommand = SelectedPackage.LaunchCommand, |
|
LastUpdateCheck = DateTimeOffset.Now |
|
}; |
|
await using var st = settingsManager.BeginTransaction(); |
|
st.Settings.InstalledPackages.Add(installedPackage); |
|
st.Settings.ActiveInstalledPackage = installedPackage.Id; |
|
EventManager.Instance.OnInstalledPackagesChanged(); |
|
|
|
HeaderText = "Installation complete!"; |
|
SubSubHeaderText = string.Empty; |
|
OneClickInstallProgress = 100; |
|
SubHeaderText = "Proceeding to Launch page in 3 seconds..."; |
|
await Task.Delay(1000); |
|
SubHeaderText = "Proceeding to Launch page in 2 seconds..."; |
|
await Task.Delay(1000); |
|
SubHeaderText = "Proceeding to Launch page in 1 second..."; |
|
await Task.Delay(1000); |
|
|
|
// should close dialog |
|
EventManager.Instance.OnOneClickInstallFinished(false); |
|
} |
|
|
|
private async Task DownloadPackage(string version) |
|
{ |
|
SubHeaderText = "Downloading package..."; |
|
|
|
var progress = new Progress<ProgressReport>(progress => |
|
{ |
|
IsIndeterminate = progress.IsIndeterminate; |
|
OneClickInstallProgress = Convert.ToInt32(progress.Percentage); |
|
EventManager.Instance.OnGlobalProgressChanged(OneClickInstallProgress); |
|
}); |
|
|
|
await SelectedPackage.DownloadPackage(version, false, progress); |
|
SubHeaderText = "Download Complete"; |
|
OneClickInstallProgress = 100; |
|
} |
|
|
|
private async Task InstallPackage() |
|
{ |
|
SelectedPackage.ConsoleOutput += (_, output) => SubSubHeaderText = output.Text; |
|
SubHeaderText = "Downloading and installing package requirements..."; |
|
|
|
var progress = new Progress<ProgressReport>(progress => |
|
{ |
|
IsIndeterminate = progress.IsIndeterminate; |
|
OneClickInstallProgress = Convert.ToInt32(progress.Percentage); |
|
EventManager.Instance.OnGlobalProgressChanged(OneClickInstallProgress); |
|
}); |
|
|
|
await SelectedPackage.InstallPackage(progress); |
|
} |
|
}
|
|
|