Refactor and enhance Download Manager application

- Added new services: IContentDialogService, ISnackbarService
- Replaced DashboardPage and DashboardViewModel with DownloadingPage, DownloadingPageViewModel, WaitingPage, and WaitingPageViewModel
- Introduced AddNewTaskPage and AddNewTaskViewModel
- Replaced DownloadServiceManger with DownloadManagerService
- Updated WPF-UI package to 3.0.4 and added HtmlAgilityPack 1.11.61
- Refactored DownloadWorker to use async methods and added retry logic
- Converted DownloadItemData to partial class with ObservableProperty attributes
- Changed initial navigation page to DownloadingPage
- Updated MainWindow navigation items and title
- Added new utility classes: DoubleUtilities, MD5Utilities, StringExtension
- Added new XAML pages and ViewModels for task management and display
- Removed obsolete DashboardPage and related files
This commit is contained in:
Misaki
2024-07-01 02:14:19 +09:00
parent 150cd3cb26
commit 3a59979efd
33 changed files with 1180 additions and 212 deletions

View File

@@ -1,32 +1,41 @@
using Downloader;
using DownloadManager.Models;
using DownloadManager.Models.UrlGetter;
using DownloadManager.Utilities;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
namespace DownloadManager.DownloaderCore;
public class DownloadWorker(DownloadItemData itemData)
{
IDownload? _worker;
DownloadItemData _downloadData = itemData;
private IDownload? _worker;
private DownloadItemData _downloadData = itemData;
public DownloadItemData DownloadData => _downloadData;
public Action<DownloadWorker> OnDownloadStarted;
public Action<DownloadWorker> OnDownloadFileCompleted;
public Action<DownloadWorker> OnDownloadStop;
public Action? OnDownloadStarted;
public Action? OnDownloadFileCompleted;
public Action? OnDownloadStop;
public bool BuildDownloadRequest()
private int retryCount = 0;
public async Task<bool> BuildDownloadRequestAsync()
{
var urlGetter = UrlGetterFactory.CreateUrlGetter(_downloadData.UrlGetterType);
var fileUrl = await urlGetter.GetFileUrl(_downloadData.Url);
if (fileUrl.Url == null || fileUrl.Name == null)
return false;
_downloadData.Url = fileUrl.Url;
_downloadData.FileName = fileUrl.Name;
_downloadData.MD5 = fileUrl.MD5;
retryCount = _downloadData.DownloadConfiguration.MaxTryAgainOnFailover;
try
{
_worker = new DownloadBuilder()
.WithUrl(_downloadData.Url)
.WithDirectory(_downloadData.FilePath)
.WithFileName(_downloadData.FileName)
.WithConfiguration(_downloadData.downloadConfiguration)
.Build();
_worker.DownloadStarted += DownloadStarted;
_worker.DownloadProgressChanged += DownloadProgressChanged;
_worker.DownloadFileCompleted += DownloadFileCompleted;
BuildWorker();
return true;
}
catch (Exception)
@@ -36,33 +45,82 @@ public class DownloadWorker(DownloadItemData itemData)
}
}
private void BuildWorker()
{
_worker = new DownloadBuilder()
.WithUrl(_downloadData.Url)
.WithDirectory(_downloadData.FilePath)
.WithFileName(_downloadData.FileName)
.WithConfiguration(_downloadData.DownloadConfiguration)
.Build();
_worker.DownloadStarted += DownloadStarted;
_worker.DownloadProgressChanged += DownloadProgressChanged;
_worker.DownloadFileCompleted += DownloadFileCompleted;
}
private void DownloadStarted(object? sender, DownloadStartedEventArgs e)
{
_downloadData.Status = DownloadStatus.Running;
OnDownloadStarted?.Invoke(this);
_downloadData.FileSize = DoubleUtilities.BytesToMegaBytes(e.TotalBytesToReceive, 2);
OnDownloadStarted?.Invoke();
}
private void DownloadProgressChanged(object? sender, DownloadProgressChangedEventArgs e)
{
_downloadData.Progress = (int)e.ProgressPercentage;
_downloadData.Speed = e.BytesPerSecondSpeed;
_downloadData.Speed = DoubleUtilities.BytesToMegaBytes(e.BytesPerSecondSpeed, 2);
}
private void DownloadFileCompleted(object? sender, AsyncCompletedEventArgs e)
private async void DownloadFileCompleted(object? sender, AsyncCompletedEventArgs e)
{
if (e.Error != null)
{
_downloadData.Status = DownloadStatus.Failed;
throw e.Error;
}
else
{
_downloadData.Status = DownloadStatus.Completed;
}
_worker!.Dispose();
OnDownloadFileCompleted?.Invoke(this);
// Check md5
if (_downloadData.MD5 != null)
{
var fileFullName = Path.Combine(_downloadData.FilePath, _downloadData.FileName!);
var md5 = MD5Utilities.GetMD5HashFromFile(fileFullName);
if (md5 != _downloadData.MD5)
{
await RetryDownload();
return;
}
}
OnDownloadFileCompleted?.Invoke();
}
}
public void StartDownload()
private async Task<bool> RetryDownload()
{
if (retryCount > 0)
{
retryCount--;
await Task.Delay(1000);
await BuildDownloadRequestAsync();
StartDownloadAsync();
return true;
}
else
{
_downloadData.Status = DownloadStatus.Failed;
return false;
}
}
public void StartDownloadAsync()
{
if (_worker == null)
return;
@@ -72,27 +130,18 @@ public class DownloadWorker(DownloadItemData itemData)
public void PauseDownload()
{
if (_worker == null)
return;
_worker.Pause();
OnDownloadStop?.Invoke(this);
_worker?.Pause();
OnDownloadStop?.Invoke();
}
public void ResumeDownload()
{
if (_worker == null)
return;
_worker.Resume();
_worker?.Resume();
}
public void StopDownload()
{
if (_worker == null)
return;
_worker.Stop();
OnDownloadStop?.Invoke(this);
_worker?.Stop();
OnDownloadStop?.Invoke();
}
}