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:
181
ViewModels/Pages/AddNewTaskViewModel.cs
Normal file
181
ViewModels/Pages/AddNewTaskViewModel.cs
Normal file
@@ -0,0 +1,181 @@
|
||||
using Downloader;
|
||||
using DownloadManager.Models;
|
||||
using DownloadManager.Models.UrlGetter;
|
||||
using DownloadManager.Views.Pages;
|
||||
using Microsoft.Win32;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using Wpf.Ui;
|
||||
using Wpf.Ui.Controls;
|
||||
|
||||
namespace DownloadManager.ViewModels.Pages
|
||||
{
|
||||
public partial class TaskData : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
private string? taskURL;
|
||||
[ObservableProperty]
|
||||
private UrlGetterType urlGetter = UrlGetterType.Direct;
|
||||
[ObservableProperty]
|
||||
private string? saveLocation;
|
||||
|
||||
[ObservableProperty]
|
||||
private int splitCount = 1;
|
||||
[ObservableProperty]
|
||||
private bool useParallelDownload = false;
|
||||
[ObservableProperty]
|
||||
private int retryCount = 3;
|
||||
|
||||
[ObservableProperty]
|
||||
private string? userAgent;
|
||||
[ObservableProperty]
|
||||
private string? cookies;
|
||||
[ObservableProperty]
|
||||
private string? proxy;
|
||||
}
|
||||
|
||||
public partial class AddNewTaskViewModel(ISnackbarService snackbarService) : ObservableObject, INavigationAware
|
||||
{
|
||||
[ObservableProperty]
|
||||
private TaskData? taskDataConfig;
|
||||
|
||||
private string _lastSaveLocation = string.Empty;
|
||||
|
||||
public void OnNavigatedTo()
|
||||
{
|
||||
TaskDataConfig = new();
|
||||
TaskDataConfig.SaveLocation = _lastSaveLocation;
|
||||
}
|
||||
|
||||
public void OnNavigatedFrom()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public void PickSaveLocation()
|
||||
{
|
||||
if (TaskDataConfig == null)
|
||||
return;
|
||||
|
||||
OpenFolderDialog openFolderDialog = new()
|
||||
{
|
||||
Multiselect = true,
|
||||
InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
|
||||
};
|
||||
|
||||
if (openFolderDialog.ShowDialog() != true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (openFolderDialog.FolderNames.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var folderName = string.Join("\n", openFolderDialog.FolderNames);
|
||||
TaskDataConfig.SaveLocation = folderName;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public async Task ApplyTask()
|
||||
{
|
||||
if (TaskDataConfig == null)
|
||||
return;
|
||||
|
||||
if (string.IsNullOrEmpty(TaskDataConfig.TaskURL))
|
||||
{
|
||||
snackbarService.Show(
|
||||
"Task URL is empty",
|
||||
"Please add at least one task url to download",
|
||||
ControlAppearance.Danger,
|
||||
new SymbolIcon(SymbolRegular.ErrorCircle24),
|
||||
TimeSpan.FromSeconds(5));
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(TaskDataConfig.SaveLocation) || !Directory.Exists(TaskDataConfig.SaveLocation))
|
||||
{
|
||||
snackbarService.Show(
|
||||
"Save location is not exists",
|
||||
"Please add a valid location",
|
||||
ControlAppearance.Danger,
|
||||
new SymbolIcon(SymbolRegular.ErrorCircle24),
|
||||
TimeSpan.FromSeconds(5));
|
||||
return;
|
||||
}
|
||||
|
||||
// Split TaskDataConfig.TaskURL to one task per line
|
||||
var taskUrls = TaskDataConfig.TaskURL.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
await Task.Run(() =>
|
||||
{
|
||||
foreach (var taskUrl in taskUrls)
|
||||
{
|
||||
if (string.IsNullOrEmpty(TaskDataConfig.TaskURL))
|
||||
{
|
||||
snackbarService.Show(
|
||||
"Invalid task URL",
|
||||
"Please add a valid task URL",
|
||||
ControlAppearance.Danger,
|
||||
new SymbolIcon(SymbolRegular.ErrorCircle24),
|
||||
TimeSpan.FromSeconds(5));
|
||||
return;
|
||||
}
|
||||
|
||||
var cookies = new CookieContainer();
|
||||
if (!string.IsNullOrEmpty(TaskDataConfig.Cookies))
|
||||
{
|
||||
var cookieStrings = TaskDataConfig.Cookies.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (var cookieString in cookieStrings)
|
||||
{
|
||||
var cookieParts = cookieString.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (cookieParts.Length != 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
cookies.Add(new Cookie(cookieParts[0].Trim(), cookieParts[1].Trim(), "/", new Uri(TaskDataConfig.Cookies).Host));
|
||||
}
|
||||
}
|
||||
|
||||
var config = new DownloadConfiguration
|
||||
{
|
||||
ChunkCount = TaskDataConfig.SplitCount,
|
||||
ParallelDownload = TaskDataConfig.UseParallelDownload,
|
||||
MaxTryAgainOnFailover = TaskDataConfig.RetryCount,
|
||||
BufferBlockSize = 10240,
|
||||
|
||||
RequestConfiguration =
|
||||
{
|
||||
UserAgent = TaskDataConfig.UserAgent,
|
||||
CookieContainer = cookies,
|
||||
Proxy = new WebProxy(TaskDataConfig.Proxy)
|
||||
}
|
||||
};
|
||||
|
||||
var data = new DownloadItemData(TaskDataConfig.SaveLocation, taskUrl, TaskDataConfig.UrlGetter, config);
|
||||
App.GetService<DownloaderCore.DownloadManagerService>().AddDownloadItem(data);
|
||||
}
|
||||
});
|
||||
|
||||
App.GetService<INavigationService>().Navigate(typeof(DownloadingPage));
|
||||
|
||||
try
|
||||
{
|
||||
await App.GetService<DownloaderCore.DownloadManagerService>().FindNextDownloadAndStart();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
snackbarService.Show(
|
||||
"Error downloading files",
|
||||
ex.Message,
|
||||
ControlAppearance.Danger,
|
||||
new SymbolIcon(SymbolRegular.ErrorCircle24),
|
||||
TimeSpan.FromSeconds(5));
|
||||
}
|
||||
|
||||
_lastSaveLocation = TaskDataConfig.SaveLocation;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
|
||||
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
|
||||
// All Rights Reserved.
|
||||
|
||||
namespace DownloadManager.ViewModels.Pages;
|
||||
|
||||
public partial class DashboardViewModel : ObservableObject
|
||||
{
|
||||
|
||||
}
|
||||
33
ViewModels/Pages/DownloadingPageViewModel.cs
Normal file
33
ViewModels/Pages/DownloadingPageViewModel.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using DownloadManager.DownloaderCore;
|
||||
using DownloadManager.Models;
|
||||
using System.Collections.ObjectModel;
|
||||
using Wpf.Ui.Controls;
|
||||
|
||||
namespace DownloadManager.ViewModels.Pages;
|
||||
|
||||
public partial class DownloadingPageViewModel : ObservableObject, INavigationAware
|
||||
{
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<DownloadItemData>? downloadingTask;
|
||||
|
||||
public void OnNavigatedFrom()
|
||||
{
|
||||
}
|
||||
|
||||
public void OnNavigatedTo()
|
||||
{
|
||||
App.GetService<DownloadManagerService>().OnActiveWorkerChanged += DownloadService_OnDownloadServiceChanged;
|
||||
|
||||
LoadTasks();
|
||||
}
|
||||
|
||||
private void DownloadService_OnDownloadServiceChanged()
|
||||
{
|
||||
LoadTasks();
|
||||
}
|
||||
|
||||
private void LoadTasks()
|
||||
{
|
||||
DownloadingTask = new(App.GetService<DownloadManagerService>().GetDownloadingTask());
|
||||
}
|
||||
}
|
||||
33
ViewModels/Pages/WaitingPageViewModel.cs
Normal file
33
ViewModels/Pages/WaitingPageViewModel.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using DownloadManager.DownloaderCore;
|
||||
using DownloadManager.Models;
|
||||
using System.Collections.ObjectModel;
|
||||
using Wpf.Ui.Controls;
|
||||
|
||||
namespace DownloadManager.ViewModels.Pages;
|
||||
|
||||
public partial class WaitingPageViewModel : ObservableObject, INavigationAware
|
||||
{
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<DownloadItemData>? waitingTask;
|
||||
|
||||
public void OnNavigatedFrom()
|
||||
{
|
||||
}
|
||||
|
||||
public void OnNavigatedTo()
|
||||
{
|
||||
App.GetService<DownloadManagerService>().OnQueuedItemChanged += DownloadService_OnQueuedItemChanged;
|
||||
|
||||
LoadTasks();
|
||||
}
|
||||
|
||||
private void DownloadService_OnQueuedItemChanged()
|
||||
{
|
||||
LoadTasks();
|
||||
}
|
||||
|
||||
private void LoadTasks()
|
||||
{
|
||||
WaitingTask = new (App.GetService<DownloadManagerService>().GetWaitingTask());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user