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

@@ -0,0 +1,13 @@
using DownloadManager.Utilities;
namespace DownloadManager.Models.UrlGetter
{
class DirectUrlGetter : IUrlGetter
{
public async Task<FileUrl> GetFileUrl(string taskUrl)
{
var fileName = System.IO.Path.GetFileName(taskUrl).ToUnescapedString();
return new FileUrl(taskUrl, fileName, null);
}
}
}

View File

@@ -0,0 +1,12 @@
namespace DownloadManager.Models.UrlGetter;
public struct FileUrl(string? url, string? name, string? md5)
{
public string? Url { get; } = url;
public string? Name { get; } = name;
public string? MD5 { get; } = md5;
}
public interface IUrlGetter
{
public Task<FileUrl> GetFileUrl(string taskUrl);
}

View File

@@ -0,0 +1,15 @@
namespace DownloadManager.Models.UrlGetter
{
public class UrlGetterFactory
{
public static IUrlGetter CreateUrlGetter(UrlGetterType type)
{
return type switch
{
UrlGetterType.Direct => new DirectUrlGetter(),
UrlGetterType.Yande => new YandeUrlGetter(),
_ => throw new ArgumentException("Invalid UrlGetterType"),
};
}
}
}

View File

@@ -0,0 +1,12 @@
using System.ComponentModel;
namespace DownloadManager.Models.UrlGetter
{
public enum UrlGetterType
{
[Description("Direct")]
Direct,
[Description("Yande post URL")]
Yande,
}
}

View File

@@ -0,0 +1,63 @@
using DownloadManager.Utilities;
using System.IO;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
namespace DownloadManager.Models.UrlGetter;
public class YandeUrlGetter : IUrlGetter
{
readonly HttpClient client = new ();
const int maxRetries = 3;
const int delayMilliseconds = 1000;
public async Task<FileUrl> GetFileUrl(string taskUrl)
{
// Get the ID of the post from the URL
var id = taskUrl.Split("https://yande.re/post/show/").Last();
for (int attempt = 0; attempt < maxRetries; attempt++)
{
try
{
var response = await client.GetAsync($"https://yande.re/post.json?tags=id:{id}");
if (response.IsSuccessStatusCode)
{
var data = await response.Content.ReadFromJsonAsync<JsonElement[]>();
if (data == null || data.Length == 0)
{
return new FileUrl(null, null, null);
}
var firstElement = data.FirstOrDefault();
if (firstElement.ValueKind != JsonValueKind.Object || !firstElement.TryGetProperty("file_url", out var fileUrlElement))
{
return new FileUrl(null, null, null);
}
if (!firstElement.TryGetProperty("md5", out var md5Element))
{
return new FileUrl(null, null, null);
}
var fileUrl = fileUrlElement.GetString();
var fileName = Path.GetFileName(fileUrl)?.ToUnescapedString();
var md5 = md5Element.GetString();
return new FileUrl(fileUrl, fileName, md5);
}
}
catch (HttpRequestException)
{
// Log the exception if needed
}
// Wait before retrying
await Task.Delay(delayMilliseconds);
}
// If all retries fail, return a FileUrl with null values
return new FileUrl(null, null, null);
}
}