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