Browse Source

Fix resume loading behavior

pull/109/head
Ionite 1 year ago
parent
commit
85b8a25baa
No known key found for this signature in database
  1. 1
      StabilityMatrix.Avalonia/ViewModels/DownloadProgressItemViewModel.cs
  2. 6
      StabilityMatrix.Avalonia/ViewModels/MainWindowViewModel.cs
  3. 14
      StabilityMatrix.Avalonia/ViewModels/ProgressManagerViewModel.cs
  4. 39
      StabilityMatrix.Core/Models/TrackedDownload.cs
  5. 2
      StabilityMatrix.Core/Services/ITrackedDownloadService.cs
  6. 6
      StabilityMatrix.Core/Services/TrackedDownloadService.cs

1
StabilityMatrix.Avalonia/ViewModels/DownloadProgressItemViewModel.cs

@ -13,6 +13,7 @@ public class DownloadProgressItemViewModel : PausableProgressItemViewModelBase
{
this.download = download;
Id = download.Id;
Name = download.FileName;
State = download.ProgressState;

6
StabilityMatrix.Avalonia/ViewModels/MainWindowViewModel.cs

@ -24,6 +24,7 @@ public partial class MainWindowViewModel : ViewModelBase
{
private readonly ISettingsManager settingsManager;
private readonly ServiceManager<ViewModelBase> dialogFactory;
private readonly ITrackedDownloadService trackedDownloadService;
private readonly IDiscordRichPresenceService discordRichPresenceService;
public string Greeting => "Welcome to Avalonia!";
@ -45,11 +46,13 @@ public partial class MainWindowViewModel : ViewModelBase
public MainWindowViewModel(
ISettingsManager settingsManager,
IDiscordRichPresenceService discordRichPresenceService,
ITrackedDownloadService trackedDownloadService,
ServiceManager<ViewModelBase> dialogFactory)
{
this.settingsManager = settingsManager;
this.dialogFactory = dialogFactory;
this.discordRichPresenceService = discordRichPresenceService;
this.trackedDownloadService = trackedDownloadService;
ProgressManagerViewModel = dialogFactory.Get<ProgressManagerViewModel>();
UpdateViewModel = dialogFactory.Get<UpdateViewModel>();
@ -81,6 +84,9 @@ public partial class MainWindowViewModel : ViewModelBase
// Initialize Discord Rich Presence (this needs LibraryDir so is set here)
discordRichPresenceService.UpdateState();
// Load in-progress downloads
ProgressManagerViewModel.AddDownloads(trackedDownloadService.Downloads);
// Index checkpoints if we dont have
Task.Run(() => settingsManager.IndexCheckpoints()).SafeFireAndForget();

14
StabilityMatrix.Avalonia/ViewModels/ProgressManagerViewModel.cs

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Avalonia.Collections;
@ -37,6 +38,19 @@ public partial class ProgressManagerViewModel : PageViewModelBase
var vm = new DownloadProgressItemViewModel(e);
ProgressItems.Add(vm);
}
public void AddDownloads(IEnumerable<TrackedDownload> downloads)
{
foreach (var download in downloads)
{
if (ProgressItems.Any(vm => vm.Id == download.Id))
{
continue;
}
var vm = new DownloadProgressItemViewModel(download);
ProgressItems.Add(vm);
}
}
public void StartEventListener()
{

39
StabilityMatrix.Core/Models/TrackedDownload.cs

@ -1,6 +1,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
using AsyncAwaitBestPractices;
using NLog;
using StabilityMatrix.Core.Helper;
using StabilityMatrix.Core.Models.FileInterfaces;
using StabilityMatrix.Core.Models.Progress;
@ -16,6 +17,8 @@ public class TrackedDownloadProgressEventArgs : EventArgs
public class TrackedDownload
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
[JsonIgnore]
private IDownloadService? downloadService;
@ -128,6 +131,7 @@ public class TrackedDownload
{
throw new InvalidOperationException($"Download state must be inactive to start, not {ProgressState}");
}
Logger.Debug("Starting download {Download}", FileName);
EnsureDownloadService();
@ -138,34 +142,59 @@ public class TrackedDownload
.ContinueWith(OnDownloadTaskCompleted);
ProgressState = ProgressState.Working;
OnProgressStateChanged(ProgressState);
}
public void Resume()
{
if (ProgressState != ProgressState.Inactive) return;
if (ProgressState != ProgressState.Inactive)
{
Logger.Warn("Attempted to resume download {Download} but it is not paused ({State})", FileName, ProgressState);
}
Logger.Debug("Resuming download {Download}", FileName);
// Read the temp file to get the current size
var tempSize = 0L;
var tempFile = DownloadDirectory.JoinFile(TempFileName);
if (tempFile.Exists)
{
tempSize = tempFile.Info.Length;
}
EnsureDownloadService();
downloadCancellationTokenSource = new CancellationTokenSource();
downloadPauseTokenSource = new CancellationTokenSource();
downloadTask = StartDownloadTask(0, AggregateCancellationTokenSource.Token)
downloadTask = StartDownloadTask(tempSize, AggregateCancellationTokenSource.Token)
.ContinueWith(OnDownloadTaskCompleted);
ProgressState = ProgressState.Working;
OnProgressStateChanged(ProgressState);
}
public void Pause()
{
if (ProgressState != ProgressState.Working) return;
if (ProgressState != ProgressState.Working)
{
Logger.Warn("Attempted to pause download {Download} but it is not in progress ({State})", FileName, ProgressState);
return;
}
Logger.Debug("Pausing download {Download}", FileName);
downloadPauseTokenSource?.Cancel();
}
public void Cancel()
{
if (ProgressState is not (ProgressState.Working or ProgressState.Inactive)) return;
if (ProgressState is not (ProgressState.Working or ProgressState.Inactive))
{
Logger.Warn("Attempted to cancel download {Download} but it is not in progress ({State})", FileName, ProgressState);
return;
}
Logger.Debug("Cancelling download {Download}", FileName);
downloadCancellationTokenSource?.Cancel();
}

2
StabilityMatrix.Core/Services/ITrackedDownloadService.cs

@ -5,6 +5,8 @@ namespace StabilityMatrix.Core.Services;
public interface ITrackedDownloadService
{
IEnumerable<TrackedDownload> Downloads { get; }
event EventHandler<TrackedDownload>? DownloadAdded;
TrackedDownload NewDownload(Uri downloadUrl, FilePath downloadPath);

6
StabilityMatrix.Core/Services/TrackedDownloadService.cs

@ -17,6 +17,8 @@ public class TrackedDownloadService : ITrackedDownloadService, IDisposable
private readonly ConcurrentDictionary<Guid, (TrackedDownload, FileStream)> downloads = new();
public IEnumerable<TrackedDownload> Downloads => downloads.Values.Select(x => x.Item1);
/// <inheritdoc />
public event EventHandler<TrackedDownload>? DownloadAdded;
@ -136,6 +138,10 @@ public class TrackedDownloadService : ITrackedDownloadService, IDisposable
download.SetDownloadService(downloadService);
downloads.TryAdd(download.Id, (download, fileStream));
// Connect to state changed event to update json file
download.ProgressStateChanged += TrackedDownload_OnProgressStateChanged;
OnDownloadAdded(download);
logger.LogDebug("Loaded in-progress download {Download}", download.FileName);

Loading…
Cancel
Save