Browse Source

Add download notifications, improve cleanup

pull/109/head
Ionite 1 year ago
parent
commit
85795b4a70
No known key found for this signature in database
  1. 40
      StabilityMatrix.Avalonia/ViewModels/ProgressManagerViewModel.cs
  2. 44
      StabilityMatrix.Core/Models/TrackedDownload.cs

40
StabilityMatrix.Avalonia/ViewModels/ProgressManagerViewModel.cs

@ -3,8 +3,10 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using Avalonia.Collections; using Avalonia.Collections;
using Avalonia.Controls.Notifications;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Polly;
using StabilityMatrix.Avalonia.Models; using StabilityMatrix.Avalonia.Models;
using StabilityMatrix.Avalonia.Services; using StabilityMatrix.Avalonia.Services;
using StabilityMatrix.Avalonia.ViewModels.Base; using StabilityMatrix.Avalonia.ViewModels.Base;
@ -22,13 +24,19 @@ namespace StabilityMatrix.Avalonia.ViewModels;
[View(typeof(ProgressManagerPage))] [View(typeof(ProgressManagerPage))]
public partial class ProgressManagerViewModel : PageViewModelBase public partial class ProgressManagerViewModel : PageViewModelBase
{ {
private readonly INotificationService notificationService;
public override string Title => "Download Manager"; public override string Title => "Download Manager";
public override IconSource IconSource => new SymbolIconSource {Symbol = Symbol.ArrowCircleDown, IsFilled = true}; public override IconSource IconSource => new SymbolIconSource {Symbol = Symbol.ArrowCircleDown, IsFilled = true};
public AvaloniaList<ProgressItemViewModelBase> ProgressItems { get; } = new(); public AvaloniaList<ProgressItemViewModelBase> ProgressItems { get; } = new();
public ProgressManagerViewModel(ITrackedDownloadService trackedDownloadService) public ProgressManagerViewModel(
ITrackedDownloadService trackedDownloadService,
INotificationService notificationService)
{ {
this.notificationService = notificationService;
// Attach to the event // Attach to the event
trackedDownloadService.DownloadAdded += TrackedDownloadService_OnDownloadAdded; trackedDownloadService.DownloadAdded += TrackedDownloadService_OnDownloadAdded;
} }
@ -36,6 +44,31 @@ public partial class ProgressManagerViewModel : PageViewModelBase
private void TrackedDownloadService_OnDownloadAdded(object? sender, TrackedDownload e) private void TrackedDownloadService_OnDownloadAdded(object? sender, TrackedDownload e)
{ {
var vm = new DownloadProgressItemViewModel(e); var vm = new DownloadProgressItemViewModel(e);
// Attach notification handlers
e.ProgressStateChanged += (s, state) =>
{
var download = s as TrackedDownload;
switch (state)
{
case ProgressState.Success:
notificationService.Show("Download Completed", $"Download of {e.FileName} completed successfully.", NotificationType.Success);
break;
case ProgressState.Failed:
var msg = "";
if (download?.Exception is { } exception)
{
msg = $"({exception.GetType().Name}) {exception.Message}";
}
notificationService.ShowPersistent("Download Failed", $"Download of {e.FileName} failed: {msg}", NotificationType.Error);
break;
case ProgressState.Cancelled:
notificationService.Show("Download Cancelled", $"Download of {e.FileName} was cancelled.", NotificationType.Warning);
break;
}
};
ProgressItems.Add(vm); ProgressItems.Add(vm);
} }
@ -52,6 +85,11 @@ public partial class ProgressManagerViewModel : PageViewModelBase
} }
} }
private void ShowFailedNotification(string title, string message)
{
notificationService.ShowPersistent(title, message, NotificationType.Error);
}
public void StartEventListener() public void StartEventListener()
{ {
EventManager.Instance.ProgressChanged += OnProgressChanged; EventManager.Instance.ProgressChanged += OnProgressChanged;

44
StabilityMatrix.Core/Models/TrackedDownload.cs

@ -48,8 +48,11 @@ public class TrackedDownload
public bool ValidateHash { get; init; } public bool ValidateHash { get; init; }
[JsonConverter(typeof(JsonStringEnumConverter))]
public ProgressState ProgressState { get; set; } = ProgressState.Inactive; public ProgressState ProgressState { get; set; } = ProgressState.Inactive;
public List<string> ExtraCleanupFileNames { get; init; } = new();
// Used for restoring progress on load // Used for restoring progress on load
public long DownloadedBytes { get; set; } public long DownloadedBytes { get; set; }
public long TotalBytes { get; set; } public long TotalBytes { get; set; }
@ -207,17 +210,37 @@ public class TrackedDownload
// Otherwise handle it manually // Otherwise handle it manually
else else
{ {
// Delete the temp file DoCleanup();
ProgressState = ProgressState.Cancelled;
OnProgressStateChanged(ProgressState);
}
}
/// <summary>
/// Deletes the temp file and any extra cleanup files
/// </summary>
private void DoCleanup()
{
try
{
DownloadDirectory.JoinFile(TempFileName).Delete();
}
catch (IOException)
{
Logger.Warn("Failed to delete temp file {TempFile}", TempFileName);
}
foreach (var extraFile in ExtraCleanupFileNames)
{
try try
{ {
DownloadDirectory.JoinFile(TempFileName).Delete(); DownloadDirectory.JoinFile(extraFile).Delete();
} }
catch (IOException) catch (IOException)
{ {
Logger.Warn("Failed to delete extra cleanup file {ExtraFile}", extraFile);
} }
ProgressState = ProgressState.Cancelled;
OnProgressStateChanged(ProgressState);
} }
} }
@ -258,17 +281,10 @@ public class TrackedDownload
ProgressState = ProgressState.Success; ProgressState = ProgressState.Success;
} }
// For failed or cancelled, delete the temp file // For failed or cancelled, delete the temp files
if (ProgressState is ProgressState.Failed or ProgressState.Cancelled) if (ProgressState is ProgressState.Failed or ProgressState.Cancelled)
{ {
// Delete the temp file DoCleanup();
try
{
DownloadDirectory.JoinFile(TempFileName).Delete();
}
catch (IOException)
{
}
} }
else if (ProgressState == ProgressState.Success) else if (ProgressState == ProgressState.Success)
{ {

Loading…
Cancel
Save