Browse Source

Merge pull request #14 from ionite34/fix-listview-selection

pull/5/head
Ionite 2 years ago committed by GitHub
parent
commit
e7771833e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      StabilityMatrix/App.xaml.cs
  2. 3
      StabilityMatrix/Helper/ProcessRunner.cs
  3. 33
      StabilityMatrix/InstallPage.xaml
  4. 11
      StabilityMatrix/InstallPage.xaml.cs
  5. 29
      StabilityMatrix/Models/Packages/A3WebUI.cs
  6. 6
      StabilityMatrix/PyVenvRunner.cs
  7. 36
      StabilityMatrix/ViewModels/InstallerViewModel.cs

1
StabilityMatrix/App.xaml.cs

@ -31,6 +31,7 @@ namespace StabilityMatrix
serviceCollection.AddTransient<MainWindowViewModel>(); serviceCollection.AddTransient<MainWindowViewModel>();
serviceCollection.AddSingleton<SettingsViewModel>(); serviceCollection.AddSingleton<SettingsViewModel>();
serviceCollection.AddSingleton<LaunchViewModel>(); serviceCollection.AddSingleton<LaunchViewModel>();
serviceCollection.AddSingleton<InstallerViewModel>();
serviceCollection.AddSingleton<IContentDialogService, ContentDialogService>(); serviceCollection.AddSingleton<IContentDialogService, ContentDialogService>();
serviceCollection.AddSingleton<ISnackbarService, SnackbarService>(); serviceCollection.AddSingleton<ISnackbarService, SnackbarService>();
serviceCollection.AddSingleton<ISettingsManager, SettingsManager>(); serviceCollection.AddSingleton<ISettingsManager, SettingsManager>();

3
StabilityMatrix/Helper/ProcessRunner.cs

@ -36,11 +36,13 @@ public static class ProcessRunner
process.StartInfo.Arguments = arguments; process.StartInfo.Arguments = arguments;
process.StartInfo.UseShellExecute = false; process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.CreateNoWindow = true; process.StartInfo.CreateNoWindow = true;
if (outputDataReceived != null) if (outputDataReceived != null)
{ {
process.OutputDataReceived += (_, args) => outputDataReceived(args.Data); process.OutputDataReceived += (_, args) => outputDataReceived(args.Data);
process.ErrorDataReceived += (_, args) => outputDataReceived(args.Data);
} }
process.Start(); process.Start();
@ -48,6 +50,7 @@ public static class ProcessRunner
if (outputDataReceived != null) if (outputDataReceived != null)
{ {
process.BeginOutputReadLine(); process.BeginOutputReadLine();
process.BeginErrorReadLine();
} }
return process; return process;

33
StabilityMatrix/InstallPage.xaml

@ -20,14 +20,32 @@
</Page.DataContext> </Page.DataContext>
<Grid Margin="16"> <Grid Margin="16">
<StackPanel Orientation="Horizontal" Margin="16" HorizontalAlignment="Left" Height="400"> <Grid.RowDefinitions>
<ListView <RowDefinition Height="Auto"/>
ItemsSource="{Binding Packages}" <RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Vertical">
<Button Content="Install" Command="{Binding InstallCommand}" Width="100" Height="50" HorizontalAlignment="Center"/>
<TextBlock Text="{Binding InstalledText}" HorizontalAlignment="Center" Padding="8"/>
<ProgressBar Visibility="{Binding ProgressBarVisibility, FallbackValue=Visible}" Value="{Binding ProgressValue, FallbackValue=10}"
IsIndeterminate="{Binding IsIndeterminate, FallbackValue=False}"
Maximum="100" Width="500"/>
</StackPanel>
<StackPanel Grid.Row="1" Orientation="Horizontal" Margin="16" HorizontalAlignment="Left" Height="400">
<ListView ItemsSource="{Binding Packages}"
SelectedItem="{Binding SelectedPackage, Mode=TwoWay}"> SelectedItem="{Binding SelectedPackage, Mode=TwoWay}">
<ListView.Style>
<Style TargetType="ListView">
<Setter Property="Background" Value="#191919"/>
</Style>
</ListView.Style>
<ListView.ItemTemplate> <ListView.ItemTemplate>
<DataTemplate DataType="{x:Type models:BasePackage}"> <DataTemplate DataType="{x:Type models:BasePackage}">
<StackPanel VerticalAlignment="Top" Margin="10,0,0,0"> <StackPanel VerticalAlignment="Top" Margin="8">
<TextBlock Text="{Binding DisplayName}" Margin="0,5,0,5" /> <TextBlock Text="{Binding DisplayName}" Margin="0,5,0,5" />
<TextBlock Text="{Binding ByAuthor}" Margin="0,0,0,5" /> <TextBlock Text="{Binding ByAuthor}" Margin="0,0,0,5" />
</StackPanel> </StackPanel>
@ -45,12 +63,5 @@
</ui:Hyperlink> </ui:Hyperlink>
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
<StackPanel Orientation="Vertical">
<Button Content="Install" Command="{Binding InstallCommand}" Width="100" Height="50" HorizontalAlignment="Center"/>
<TextBlock Text="{Binding InstalledText}" HorizontalAlignment="Center" Padding="8"/>
<ProgressBar Visibility="{Binding ProgressBarVisibility}" Value="{Binding ProgressValue, FallbackValue=10}"
IsIndeterminate="{Binding IsIndeterminate, FallbackValue=True}"
Maximum="100" Width="500"/>
</StackPanel>
</Grid> </Grid>
</Page> </Page>

11
StabilityMatrix/InstallPage.xaml.cs

@ -12,15 +12,18 @@ namespace StabilityMatrix
/// </summary> /// </summary>
public sealed partial class InstallPage : Page public sealed partial class InstallPage : Page
{ {
public InstallPage() private readonly InstallerViewModel viewModel;
{
public InstallPage(InstallerViewModel viewModel)
{
this.viewModel = viewModel;
InitializeComponent(); InitializeComponent();
DataContext = new InstallerViewModel(); DataContext = viewModel;
} }
private async void InstallPage_OnLoaded(object sender, RoutedEventArgs e) private async void InstallPage_OnLoaded(object sender, RoutedEventArgs e)
{ {
await ((InstallerViewModel) DataContext).OnLoaded(); await viewModel.OnLoaded();
} }
} }
} }

29
StabilityMatrix/Models/Packages/A3WebUI.cs

@ -3,6 +3,7 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Refit; using Refit;
using StabilityMatrix.Api; using StabilityMatrix.Api;
@ -30,9 +31,20 @@ public class A3WebUI: BasePackage
using var client = new HttpClient {Timeout = TimeSpan.FromMinutes(5)}; using var client = new HttpClient {Timeout = TimeSpan.FromMinutes(5)};
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("StabilityMatrix", "1.0")); client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("StabilityMatrix", "1.0"));
await using var file = new FileStream(DownloadLocation, FileMode.Create, FileAccess.Write, FileShare.None); await using var file = new FileStream(DownloadLocation, FileMode.Create, FileAccess.Write, FileShare.None);
using var response = await client.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead);
var length = response.Content.Headers.ContentLength;
long contentLength = 0;
var retryCount = 0;
var response = await client.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead);
while (contentLength == 0 && retryCount++ < 5)
{
response = await client.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead);
contentLength = response.Content.Headers.ContentLength ?? 0;
Debug.WriteLine("Retrying...");
Thread.Sleep(50);
}
var isIndeterminate = contentLength == 0;
await using var stream = await response.Content.ReadAsStreamAsync(); await using var stream = await response.Content.ReadAsStreamAsync();
var totalBytesRead = 0; var totalBytesRead = 0;
while (true) while (true)
@ -44,9 +56,16 @@ public class A3WebUI: BasePackage
totalBytesRead += bytesRead; totalBytesRead += bytesRead;
var progress = (int) (totalBytesRead * 100d / length); if (isIndeterminate)
Debug.WriteLine($"Progress; {progress}"); {
OnDownloadProgressChanged(progress); OnDownloadProgressChanged(-1);
}
else
{
var progress = (int) (totalBytesRead * 100d / contentLength);
Debug.WriteLine($"Progress; {progress}");
OnDownloadProgressChanged(progress);
}
} }
await file.FlushAsync(); await file.FlushAsync();

6
StabilityMatrix/PyVenvRunner.cs

@ -53,11 +53,13 @@ public class PyVenvRunner: IDisposable
// Create venv // Create venv
var venvProc = ProcessRunner.StartProcess(PyRunner.ExePath, "-m virtualenv " + RootPath); var venvProc = ProcessRunner.StartProcess(PyRunner.ExePath, "-m virtualenv " + RootPath);
await venvProc.WaitForExitAsync(); await venvProc.WaitForExitAsync();
// Check return code // Check return code
var returnCode = venvProc.ExitCode; var returnCode = venvProc.ExitCode;
if (returnCode != 0) if (returnCode != 0)
{ {
var output = await venvProc.StandardOutput.ReadToEndAsync(); var output = await venvProc.StandardOutput.ReadToEndAsync();
output += await venvProc.StandardError.ReadToEndAsync();
throw new InvalidOperationException($"Venv creation failed with code {returnCode}: {output}"); throw new InvalidOperationException($"Venv creation failed with code {returnCode}: {output}");
} }
} }
@ -81,4 +83,4 @@ public class PyVenvRunner: IDisposable
Process?.Dispose(); Process?.Dispose();
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
} }

36
StabilityMatrix/ViewModels/InstallerViewModel.cs

@ -12,7 +12,7 @@ using CommunityToolkit.Mvvm.Input;
namespace StabilityMatrix.ViewModels; namespace StabilityMatrix.ViewModels;
internal class InstallerViewModel : INotifyPropertyChanged public class InstallerViewModel : INotifyPropertyChanged
{ {
private string installedText; private string installedText;
private int progressValue; private int progressValue;
@ -23,19 +23,20 @@ internal class InstallerViewModel : INotifyPropertyChanged
{ {
InstalledText = "shrug"; InstalledText = "shrug";
ProgressValue = 0; ProgressValue = 0;
Packages = new ObservableCollection<BasePackage>
{
new A3WebUI(),
new DankDiffusion()
};
SelectedPackage = Packages[0];
} }
public Task OnLoaded() public Task OnLoaded()
{ {
SelectedPackage = Packages.First();
return Task.CompletedTask; return Task.CompletedTask;
} }
public static ObservableCollection<BasePackage> Packages => new() public ObservableCollection<BasePackage> Packages { get; }
{
new A3WebUI(),
new DankDiffusion()
};
public string InstalledText public string InstalledText
{ {
@ -81,9 +82,26 @@ internal class InstallerViewModel : INotifyPropertyChanged
} }
} }
public Visibility ProgressBarVisibility => ProgressValue > 0 ? Visibility.Visible : Visibility.Collapsed; public Visibility ProgressBarVisibility => ProgressValue > 0 || IsIndeterminate ? Visibility.Visible : Visibility.Collapsed;
public AsyncRelayCommand InstallCommand => new(async () => await SelectedPackage.DownloadPackage()); public AsyncRelayCommand InstallCommand => new(async () =>
{
SelectedPackage.DownloadProgressChanged += (_, progress) =>
{
if (progress == -1)
{
IsIndeterminate = true;
ProgressValue = 1;
}
else
{
IsIndeterminate = false;
ProgressValue = progress;
}
};
SelectedPackage.DownloadComplete += (_, _) => InstalledText = "Download Complete";
await SelectedPackage.DownloadPackage();
});
private async Task<bool> InstallGitIfNecessary() private async Task<bool> InstallGitIfNecessary()
{ {
var gitOutput = await ProcessRunner.GetProcessOutputAsync("git", "--version"); var gitOutput = await ProcessRunner.GetProcessOutputAsync("git", "--version");

Loading…
Cancel
Save