Ionite
1 year ago
committed by
GitHub
20 changed files with 299 additions and 248 deletions
@ -0,0 +1,72 @@ |
|||||||
|
<ui:ContentDialog |
||||||
|
CloseButtonText="Close" |
||||||
|
Loaded="OneClickInstallDialog_OnLoaded" |
||||||
|
Title="Stable Diffusion WebUI Installer" |
||||||
|
d:DataContext="{d:DesignInstance Type=viewModels:OneClickInstallViewModel, |
||||||
|
IsDesignTimeCreatable=True}" |
||||||
|
d:DesignHeight="512" |
||||||
|
d:DesignWidth="640" |
||||||
|
mc:Ignorable="d" |
||||||
|
ui:Design.Background="{DynamicResource ApplicationBackgroundBrush}" |
||||||
|
ui:Design.Foreground="{DynamicResource TextFillColorPrimaryBrush}" |
||||||
|
x:Class="StabilityMatrix.OneClickInstallDialog" |
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
||||||
|
xmlns:local="clr-namespace:StabilityMatrix" |
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
||||||
|
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml" |
||||||
|
xmlns:viewModels="clr-namespace:StabilityMatrix.ViewModels" |
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
||||||
|
|
||||||
|
<ui:ContentDialog.Resources> |
||||||
|
<!-- ReSharper disable once Xaml.StaticResourceNotResolved --> |
||||||
|
<Style BasedOn="{StaticResource {x:Type ui:ContentDialog}}" TargetType="{x:Type local:OneClickInstallDialog}" /> |
||||||
|
<BooleanToVisibilityConverter x:Key="BoolToVisConverter" /> |
||||||
|
</ui:ContentDialog.Resources> |
||||||
|
|
||||||
|
<Grid MaxHeight="900" VerticalAlignment="Stretch"> |
||||||
|
<Grid.RowDefinitions> |
||||||
|
<RowDefinition Height="Auto" /> |
||||||
|
<RowDefinition Height="Auto" /> |
||||||
|
<RowDefinition Height="1*" /> |
||||||
|
<RowDefinition Height="0.25*" /> |
||||||
|
</Grid.RowDefinitions> |
||||||
|
<TextBlock Text="{Binding HeaderText}" |
||||||
|
TextWrapping="Wrap" |
||||||
|
VerticalAlignment="Top" HorizontalAlignment="Center" |
||||||
|
FontSize="36" FontWeight="Light" Margin="8" /> |
||||||
|
<TextBlock Grid.Row="1" |
||||||
|
Text="{Binding SubHeaderText}" |
||||||
|
TextWrapping="Wrap" TextAlignment="Center" |
||||||
|
VerticalAlignment="Top" HorizontalAlignment="Center" |
||||||
|
FontSize="16" FontWeight="Light" Margin="8"> |
||||||
|
</TextBlock> |
||||||
|
|
||||||
|
<StackPanel Grid.Row="2" VerticalAlignment="Center"> |
||||||
|
<ProgressBar Maximum="100" Value="{Binding OneClickInstallProgress}" |
||||||
|
Visibility="{Binding ProgressBarVisibility}" |
||||||
|
IsIndeterminate="{Binding IsIndeterminate}" |
||||||
|
Margin="16" /> |
||||||
|
<ui:Button |
||||||
|
Visibility="{Binding ShowInstallButton, Converter={StaticResource BoolToVisConverter}}" |
||||||
|
Content="Install" |
||||||
|
Command="{Binding InstallCommand}" |
||||||
|
FontSize="32" |
||||||
|
HorizontalAlignment="Center" |
||||||
|
Appearance="Primary" |
||||||
|
Margin="16" |
||||||
|
Padding="16, 8, 16, 8" /> |
||||||
|
</StackPanel> |
||||||
|
|
||||||
|
<ui:Button Grid.Row="3" |
||||||
|
Appearance="Transparent" |
||||||
|
Visibility="{Binding ShowInstallButton, Converter={StaticResource BoolToVisConverter}}" |
||||||
|
Command="{Binding ToggleAdvancedModeCommand}" |
||||||
|
Content="Skip first-time setup" |
||||||
|
FontSize="14" |
||||||
|
HorizontalAlignment="Center" |
||||||
|
Margin="16" |
||||||
|
VerticalAlignment="Bottom" /> |
||||||
|
</Grid> |
||||||
|
|
||||||
|
</ui:ContentDialog> |
@ -0,0 +1,24 @@ |
|||||||
|
using System.Windows; |
||||||
|
using StabilityMatrix.ViewModels; |
||||||
|
using Wpf.Ui.Contracts; |
||||||
|
using Wpf.Ui.Controls.ContentDialogControl; |
||||||
|
|
||||||
|
namespace StabilityMatrix; |
||||||
|
|
||||||
|
public partial class OneClickInstallDialog : ContentDialog |
||||||
|
{ |
||||||
|
private readonly OneClickInstallViewModel viewModel; |
||||||
|
|
||||||
|
public OneClickInstallDialog(IContentDialogService dialogService, OneClickInstallViewModel viewModel) : base( |
||||||
|
dialogService.GetContentPresenter()) |
||||||
|
{ |
||||||
|
this.viewModel = viewModel; |
||||||
|
InitializeComponent(); |
||||||
|
DataContext = viewModel; |
||||||
|
} |
||||||
|
|
||||||
|
private void OneClickInstallDialog_OnLoaded(object sender, RoutedEventArgs e) |
||||||
|
{ |
||||||
|
//viewModel.OnLoad(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,162 @@ |
|||||||
|
using System; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using System.Windows; |
||||||
|
using CommunityToolkit.Mvvm.ComponentModel; |
||||||
|
using CommunityToolkit.Mvvm.Input; |
||||||
|
using Microsoft.Extensions.Logging; |
||||||
|
using StabilityMatrix.Helper; |
||||||
|
using StabilityMatrix.Models; |
||||||
|
using StabilityMatrix.Python; |
||||||
|
using EventManager = StabilityMatrix.Helper.EventManager; |
||||||
|
|
||||||
|
namespace StabilityMatrix.ViewModels; |
||||||
|
|
||||||
|
public partial class OneClickInstallViewModel : ObservableObject |
||||||
|
{ |
||||||
|
private readonly ISettingsManager settingsManager; |
||||||
|
private readonly IPackageFactory packageFactory; |
||||||
|
private readonly IPrerequisiteHelper prerequisiteHelper; |
||||||
|
private readonly ILogger<MainWindowViewModel> logger; |
||||||
|
private readonly IPyRunner pyRunner; |
||||||
|
private const string DefaultPackageName = "stable-diffusion-webui"; |
||||||
|
|
||||||
|
[ObservableProperty] private string headerText; |
||||||
|
[ObservableProperty] private string subHeaderText; |
||||||
|
[ObservableProperty] private bool showInstallButton; |
||||||
|
[ObservableProperty] private bool isIndeterminate; |
||||||
|
|
||||||
|
[ObservableProperty] |
||||||
|
[NotifyPropertyChangedFor(nameof(ProgressBarVisibility))] |
||||||
|
private int oneClickInstallProgress; |
||||||
|
|
||||||
|
|
||||||
|
public Visibility ProgressBarVisibility => OneClickInstallProgress > 0 ? Visibility.Visible : Visibility.Collapsed; |
||||||
|
|
||||||
|
public OneClickInstallViewModel(ISettingsManager settingsManager, IPackageFactory packageFactory, |
||||||
|
IPrerequisiteHelper prerequisiteHelper, ILogger<MainWindowViewModel> logger, IPyRunner pyRunner) |
||||||
|
{ |
||||||
|
this.settingsManager = settingsManager; |
||||||
|
this.packageFactory = packageFactory; |
||||||
|
this.prerequisiteHelper = prerequisiteHelper; |
||||||
|
this.logger = logger; |
||||||
|
this.pyRunner = pyRunner; |
||||||
|
|
||||||
|
HeaderText = "Click the Install button below to get started!"; |
||||||
|
SubHeaderText = |
||||||
|
"This will install the latest version of Stable Diffusion WebUI by Automatic1111.\nIf you don't know what this means, don't worry, you'll be generating images soon!"; |
||||||
|
ShowInstallButton = true; |
||||||
|
} |
||||||
|
|
||||||
|
[RelayCommand] |
||||||
|
private async Task Install() |
||||||
|
{ |
||||||
|
ShowInstallButton = false; |
||||||
|
await DoInstall(); |
||||||
|
ShowInstallButton = true; |
||||||
|
} |
||||||
|
|
||||||
|
[RelayCommand] |
||||||
|
private Task ToggleAdvancedMode() |
||||||
|
{ |
||||||
|
EventManager.Instance.OnOneClickInstallFinished(); |
||||||
|
return Task.CompletedTask; |
||||||
|
} |
||||||
|
|
||||||
|
private async Task DoInstall() |
||||||
|
{ |
||||||
|
var a1111 = packageFactory.FindPackageByName(DefaultPackageName)!; |
||||||
|
HeaderText = "Installing Stable Diffusion WebUI..."; |
||||||
|
// check git |
||||||
|
var gitProcess = await prerequisiteHelper.InstallGitIfNecessary(); |
||||||
|
if (gitProcess != null) // git isn't installed |
||||||
|
{ |
||||||
|
IsIndeterminate = true; |
||||||
|
SubHeaderText = "Installing git..."; |
||||||
|
await gitProcess.WaitForExitAsync(); |
||||||
|
if (gitProcess.ExitCode != 0) |
||||||
|
{ |
||||||
|
HeaderText = "Installation failed"; |
||||||
|
SubHeaderText = "Error installing git. Please try again later."; |
||||||
|
OneClickInstallProgress = 0; |
||||||
|
logger.LogError($"Git install failed with exit code {gitProcess.ExitCode}"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
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 a1111.GetLatestVersion(); |
||||||
|
a1111.InstallLocation += "\\stable-diffusion-webui"; |
||||||
|
await DownloadPackage(a1111, latestVersion); |
||||||
|
await InstallPackage(a1111); |
||||||
|
|
||||||
|
var package = new InstalledPackage |
||||||
|
{ |
||||||
|
DisplayName = a1111.DisplayName, |
||||||
|
Path = a1111.InstallLocation, |
||||||
|
Id = Guid.NewGuid(), |
||||||
|
PackageName = a1111.Name, |
||||||
|
PackageVersion = latestVersion, |
||||||
|
LaunchCommand = a1111.LaunchCommand, |
||||||
|
LastUpdateCheck = DateTimeOffset.Now |
||||||
|
}; |
||||||
|
settingsManager.AddInstalledPackage(package); |
||||||
|
settingsManager.SetActiveInstalledPackage(package); |
||||||
|
EventManager.Instance.OnInstalledPackagesChanged(); |
||||||
|
|
||||||
|
HeaderText = "Installation complete!"; |
||||||
|
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(); |
||||||
|
} |
||||||
|
|
||||||
|
private Task<string?> DownloadPackage(BasePackage selectedPackage, string version) |
||||||
|
{ |
||||||
|
selectedPackage.DownloadProgressChanged += SelectedPackageOnProgressChanged; |
||||||
|
selectedPackage.DownloadComplete += (_, _) => SubHeaderText = "Download Complete"; |
||||||
|
SubHeaderText = "Downloading package..."; |
||||||
|
return selectedPackage.DownloadPackage(version: version); |
||||||
|
} |
||||||
|
|
||||||
|
private async Task InstallPackage(BasePackage selectedPackage) |
||||||
|
{ |
||||||
|
selectedPackage.InstallProgressChanged += SelectedPackageOnProgressChanged; |
||||||
|
selectedPackage.InstallComplete += (_, _) => HeaderText = "Install Complete"; |
||||||
|
SubHeaderText = "Installing package..."; |
||||||
|
await selectedPackage.InstallPackage(); |
||||||
|
} |
||||||
|
|
||||||
|
private void SelectedPackageOnProgressChanged(object? sender, int progress) |
||||||
|
{ |
||||||
|
if (progress == -1) |
||||||
|
{ |
||||||
|
IsIndeterminate = true; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
IsIndeterminate = false; |
||||||
|
OneClickInstallProgress = progress; |
||||||
|
} |
||||||
|
|
||||||
|
EventManager.Instance.OnGlobalProgressChanged(progress); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue