Browse Source

Updated download service to use IProgress

pull/5/head
JT 1 year ago
parent
commit
4b96406af0
  1. 19
      StabilityMatrix/CheckpointBrowserPage.xaml
  2. 23
      StabilityMatrix/DesignData/MockCheckpointBrowserViewModel.cs
  3. 12
      StabilityMatrix/Helper/PrerequisiteHelper.cs
  4. 16
      StabilityMatrix/Models/Packages/BaseGitPackage.cs
  5. 23
      StabilityMatrix/Services/DownloadService.cs
  6. 5
      StabilityMatrix/Services/IDownloadService.cs
  7. 49
      StabilityMatrix/ViewModels/CheckpointBrowserCardViewModel.cs
  8. 2
      StabilityMatrix/ViewModels/CheckpointBrowserViewModel.cs
  9. 4
      StabilityMatrix/ViewModels/ProgressViewModel.cs

19
StabilityMatrix/CheckpointBrowserPage.xaml

@ -8,7 +8,6 @@
ui:Design.Background="{DynamicResource ApplicationBackgroundBrush}"
ui:Design.Foreground="{DynamicResource TextFillColorPrimaryBrush}"
x:Class="StabilityMatrix.CheckpointBrowserPage"
x:Name="CheckpointBrowserPg"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:api="clr-namespace:StabilityMatrix.Models.Api"
xmlns:converters="clr-namespace:StabilityMatrix.Converters"
@ -41,18 +40,18 @@
FontSize="11"
Foreground="{DynamicResource TextFillColorTertiaryBrush}"
Margin="0,2,0,0"
Text="{Binding ModelVersions[0].Name}"
Text="{Binding CivitModel.ModelVersions[0].Name}"
VerticalAlignment="Center" />
<Grid>
<Image
Margin="0,8,0,8"
MaxHeight="300"
Source="{Binding ModelVersions[0].Images[0].Url, Converter={StaticResource UriToBitmapConverter}}"
Source="{Binding CivitModel.ModelVersions[0].Images[0].Url, Converter={StaticResource UriToBitmapConverter}}"
Stretch="UniformToFill" />
<ui:Button
Appearance="Info"
Command="{Binding OpenModelCommand}"
CommandParameter="{Binding}"
CommandParameter="{Binding CivitModel}"
HorizontalAlignment="Right"
Margin="0,16,8,0"
VerticalAlignment="Top">
@ -64,21 +63,21 @@
HorizontalAlignment="Stretch"
Margin="0,8,0,8"
VerticalAlignment="Stretch"
Visibility="{Binding DataContext.ImportCommand.IsRunning, Source={x:Reference CheckpointBrowserPg}, Converter={StaticResource BoolToVisibilityConverter}}" />
Visibility="{Binding ImportCommand.IsRunning, Converter={StaticResource BoolToVisibilityConverter}}" />
<StackPanel
HorizontalAlignment="Stretch"
Orientation="Vertical"
VerticalAlignment="Center"
Visibility="{Binding DataContext.ImportCommand.IsRunning, Source={x:Reference CheckpointBrowserPg}, Converter={StaticResource BoolToVisibilityConverter}}">
Visibility="{Binding ImportCommand.IsRunning, Converter={StaticResource BoolToVisibilityConverter}}">
<ui:ProgressRing
HorizontalAlignment="Center"
IsIndeterminate="False"
Progress="{Binding DataContext.ImportProgress, Source={x:Reference CheckpointBrowserPg}}"
Progress="{Binding Value}"
VerticalAlignment="Center" />
<TextBlock
HorizontalAlignment="Center"
Margin="0,8,0,0"
Text="{Binding ImportStatus, FallbackValue=Importing...}"
Text="{Binding Text, FallbackValue=Importing...}"
VerticalAlignment="Center" />
</StackPanel>
</Grid>
@ -88,8 +87,8 @@
</Grid.ColumnDefinitions>
<ui:Button
Appearance="Primary"
Command="{Binding DataContext.ImportCommand, Source={x:Reference CheckpointBrowserPg}}"
CommandParameter="{Binding}"
Command="{Binding ImportCommand}"
CommandParameter="{Binding CivitModel}"
Content="Import"
HorizontalAlignment="Stretch"
Margin="0,8,0,0" />

23
StabilityMatrix/DesignData/MockCheckpointBrowserViewModel.cs

@ -10,22 +10,25 @@ public class MockCheckpointBrowserViewModel : CheckpointBrowserViewModel
{
public MockCheckpointBrowserViewModel() : base(null!, null!)
{
CivitModels = new ObservableCollection<CivitModel>
ModelCards = new ObservableCollection<CheckpointBrowserCardViewModel>
{
new()
new (null!, null!)
{
Name = "bb95 Furry Mix",
ModelVersions = new[]
CivitModel = new()
{
new CivitModelVersion
Name = "bb95 Furry Mix",
ModelVersions = new[]
{
Name = "v7.0",
Images = new[]
new CivitModelVersion
{
new CivitImage
Name = "v7.0",
Images = new[]
{
Url =
"https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/1547f350-461a-4cd0-a753-0544aa81e4fc/width=450/00000-4137473915.jpeg"
new CivitImage
{
Url =
"https://image.civitai.com/xG1nkqKTMzGDvpLrqFT7WA/1547f350-461a-4cd0-a753-0544aa81e4fc/width=450/00000-4137473915.jpeg"
}
}
}
}

12
StabilityMatrix/Helper/PrerequisiteHelper.cs

@ -59,13 +59,13 @@ public class PrerequisiteHelper : IPrerequisiteHelper
if (!File.Exists(PortableGitDownloadPath))
{
downloadService.DownloadProgressChanged += OnDownloadProgressChanged;
downloadService.DownloadComplete += OnDownloadComplete;
var progress = new Progress<ProgressReport>(progress =>
{
OnDownloadProgressChanged(this, progress);
});
await downloadService.DownloadToFileAsync(portableGitUrl, PortableGitDownloadPath);
downloadService.DownloadProgressChanged -= OnDownloadProgressChanged;
downloadService.DownloadComplete -= OnDownloadComplete;
await downloadService.DownloadToFileAsync(portableGitUrl, PortableGitDownloadPath, progress: progress);
OnDownloadComplete(this, new ProgressReport(progress: 1f));
}
await UnzipGit();

16
StabilityMatrix/Models/Packages/BaseGitPackage.cs

@ -108,19 +108,13 @@ public abstract class BaseGitPackage : BasePackage
Directory.CreateDirectory(DownloadLocation.Replace($"{Name}.zip", ""));
}
void DownloadProgressHandler(object? _, ProgressReport progress) =>
var progress = new Progress<ProgressReport>(progress =>
{
DownloadServiceOnDownloadProgressChanged(progress, isUpdate);
void DownloadFinishedHandler(object? _, ProgressReport downloadLocation) =>
DownloadServiceOnDownloadFinished(downloadLocation, isUpdate);
DownloadService.DownloadProgressChanged += DownloadProgressHandler;
DownloadService.DownloadComplete += DownloadFinishedHandler;
await DownloadService.DownloadToFileAsync(downloadUrl, DownloadLocation);
});
DownloadService.DownloadProgressChanged -= DownloadProgressHandler;
DownloadService.DownloadComplete -= DownloadFinishedHandler;
await DownloadService.DownloadToFileAsync(downloadUrl, DownloadLocation, progress: progress);
DownloadServiceOnDownloadFinished(new ProgressReport(100, "Download Complete"), isUpdate);
return version;
}

23
StabilityMatrix/Services/DownloadService.cs

@ -19,11 +19,9 @@ public class DownloadService : IDownloadService
this.logger = logger;
this.httpClientFactory = httpClientFactory;
}
public event EventHandler<ProgressReport>? DownloadProgressChanged;
public event EventHandler<ProgressReport>? DownloadComplete;
public async Task DownloadToFileAsync(string downloadUrl, string downloadLocation, int bufferSize = ushort.MaxValue)
public async Task DownloadToFileAsync(string downloadUrl, string downloadLocation, int bufferSize = ushort.MaxValue,
IProgress<ProgressReport>? progress = null)
{
using var client = httpClientFactory.CreateClient();
client.Timeout = TimeSpan.FromMinutes(5);
@ -47,7 +45,7 @@ public class DownloadService : IDownloadService
var isIndeterminate = contentLength == 0;
await using var stream = await response.Content.ReadAsStreamAsync();
var totalBytesRead = 0;
var totalBytesRead = 0L;
while (true)
{
var buffer = new byte[bufferSize];
@ -59,22 +57,15 @@ public class DownloadService : IDownloadService
if (isIndeterminate)
{
OnDownloadProgressChanged(-1);
progress?.Report(new ProgressReport(-1, isIndeterminate: true));
}
else
{
var progress = totalBytesRead / (double) contentLength;
OnDownloadProgressChanged(progress);
progress?.Report(new ProgressReport(current: Convert.ToUInt64(totalBytesRead),
total: Convert.ToUInt64(contentLength)));
}
}
await file.FlushAsync();
OnDownloadComplete(downloadLocation);
}
private void OnDownloadProgressChanged(double progress) =>
DownloadProgressChanged?.Invoke(this, new ProgressReport(progress));
private void OnDownloadComplete(string path) =>
DownloadComplete?.Invoke(this, new ProgressReport(progress: 100f, message: path));
}

5
StabilityMatrix/Services/IDownloadService.cs

@ -6,7 +6,6 @@ namespace StabilityMatrix.Services;
public interface IDownloadService
{
event EventHandler<ProgressReport>? DownloadProgressChanged;
event EventHandler<ProgressReport>? DownloadComplete;
Task DownloadToFileAsync(string downloadUrl, string downloadLocation, int bufferSize = ushort.MaxValue);
Task DownloadToFileAsync(string downloadUrl, string downloadLocation, int bufferSize = ushort.MaxValue,
IProgress<ProgressReport>? progress = null);
}

49
StabilityMatrix/ViewModels/CheckpointBrowserCardViewModel.cs

@ -1,34 +1,28 @@
using System.Diagnostics;
using System;
using System.Diagnostics;
using System.IO;
using System.Net.Mime;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using System.Windows;
using CommunityToolkit.Mvvm.Input;
using StabilityMatrix.Models;
using StabilityMatrix.Models.Api;
using StabilityMatrix.Services;
namespace StabilityMatrix.ViewModels;
public partial class CheckpointBrowserCardViewModel : ObservableObject
public partial class CheckpointBrowserCardViewModel : ProgressViewModel
{
private readonly IDownloadService downloadService;
public CivitModel CivitModel { get; init; }
[ObservableProperty] private int importProgress;
[ObservableProperty] private string importStatus;
public CheckpointBrowserCardViewModel(CivitModel civitModel)
{
CivitModel = civitModel;
}
private void DownloadServiceOnDownloadComplete(object? sender, ProgressReport e)
{
ImportStatus = "Import complete!";
ImportProgress = 100;
}
private void DownloadServiceOnDownloadProgressChanged(object? sender, ProgressReport e)
public override Visibility ProgressVisibility => Value > 0 ? Visibility.Visible : Visibility.Collapsed;
public override Visibility TextVisibility => Value > 0 ? Visibility.Visible : Visibility.Collapsed;
public CheckpointBrowserCardViewModel(CivitModel civitModel, IDownloadService downloadService)
{
ImportProgress = (int)e.Percentage;
ImportStatus = $"Importing... {e.Percentage}%";
this.downloadService = downloadService;
CivitModel = civitModel;
}
[RelayCommand]
@ -44,20 +38,21 @@ public partial class CheckpointBrowserCardViewModel : ObservableObject
[RelayCommand]
private async Task Import(CivitModel model)
{
IsIndeterminate = false;
ImportStatus = "Downloading...";
Text = "Downloading...";
var latestModelFile = model.ModelVersions[0].Files[0];
var downloadPath = Path.Combine(SharedFolders.SharedFoldersPath,
SharedFolders.SharedFolderTypeToName(model.Type.ToSharedFolderType()), latestModelFile.Name);
downloadService.DownloadProgressChanged += DownloadServiceOnDownloadProgressChanged;
downloadService.DownloadComplete += DownloadServiceOnDownloadComplete;
await downloadService.DownloadToFileAsync(latestModelFile.DownloadUrl, downloadPath);
var progress = new Progress<ProgressReport>(progress =>
{
Value = progress.Percentage;
Text = $"Importing... {progress.Percentage}%";
});
await downloadService.DownloadToFileAsync(latestModelFile.DownloadUrl, downloadPath, progress: progress);
downloadService.DownloadProgressChanged -= DownloadServiceOnDownloadProgressChanged;
downloadService.DownloadComplete -= DownloadServiceOnDownloadComplete;
Text = "Import complete!";
Value = 100;
}
}

2
StabilityMatrix/ViewModels/CheckpointBrowserViewModel.cs

@ -76,7 +76,7 @@ public partial class CheckpointBrowserViewModel : ObservableObject
CanGoToPreviousPage = CurrentPageNumber > 1;
CanGoToNextPage = CurrentPageNumber < TotalPages;
ModelCards = new ObservableCollection<CheckpointBrowserCardViewModel>(models.Items.Select(
m => new CheckpointBrowserCardViewModel { CivitModel = m }));
m => new CheckpointBrowserCardViewModel(m, downloadService)));
ShowMainLoadingSpinner = false;
Logger.Debug($"Found {models.Items.Length} models");

4
StabilityMatrix/ViewModels/ProgressViewModel.cs

@ -22,7 +22,7 @@ public partial class ProgressViewModel : ObservableObject
[NotifyPropertyChangedFor(nameof(ProgressVisibility))]
private bool isProgressVisible;
public Visibility ProgressVisibility => IsProgressVisible? Visibility.Visible : Visibility.Collapsed;
public virtual Visibility ProgressVisibility => IsProgressVisible ? Visibility.Visible : Visibility.Collapsed;
public Visibility TextVisibility => string.IsNullOrEmpty(Text) ? Visibility.Collapsed : Visibility.Visible;
public virtual Visibility TextVisibility => string.IsNullOrEmpty(Text) ? Visibility.Collapsed : Visibility.Visible;
}

Loading…
Cancel
Save