Refactor and enhance DownloadManager application
Refactored and enhanced the DownloadManager application with significant updates across multiple files. Key changes include: - **App.xaml.cs**: Re-added necessary imports, updated service registrations, and made `OnStartup` asynchronous. - **DownloadManager.csproj**: Updated target framework, application icon, and added assembly version. - **DownloadManager.sln**: Updated project format and added configurations for multiple platforms. - **DownloadManagerService.cs**: Added `HistoryStorageService` dependency, introduced `Initial` method, and improved task management. - **DownloadWorker.cs**: Enhanced error handling and changed `StartDownloadAsync` to `StartDownload`. - **ViewModels**: Refactored to use dependency injection, updated task initialization, and added new commands for settings management. - **UI Updates**: Improved `DownloadingPage.xaml` and `WaitingPage.xaml` with `ListView` and added headers. Restructured `SettingsPage.xaml` for better organization and added new settings options. - **MainWindow**: Enhanced navigation and applied user-defined themes and backdrops. - **New Files**: Added `HistoryStorageService.cs`, `ThemeToIndexConverter.cs`, `CompletedItemData.cs`, `Settings.Designer.cs`, `Settings.settings`, `Constants.cs`, `CompletedPageViewModel.cs`, `CompletedPage.xaml`, and `CompletedPage.xaml.cs` to support new features and improvements. These changes aim to improve the application's robustness, maintainability, and user experience.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using Downloader;
|
||||
using DownloadManager.DownloaderCore;
|
||||
using DownloadManager.Models;
|
||||
using DownloadManager.Models.UrlGetter;
|
||||
using DownloadManager.Views.Pages;
|
||||
@@ -34,17 +35,20 @@ namespace DownloadManager.ViewModels.Pages
|
||||
private string? proxy;
|
||||
}
|
||||
|
||||
public partial class AddNewTaskViewModel(ISnackbarService snackbarService) : ObservableObject, INavigationAware
|
||||
public partial class AddNewTaskViewModel(ISnackbarService snackbarService, DownloadManagerService downloadManager) : ObservableObject, INavigationAware
|
||||
{
|
||||
[ObservableProperty]
|
||||
private TaskData? taskDataConfig;
|
||||
|
||||
private string _lastSaveLocation = string.Empty;
|
||||
|
||||
public void OnNavigatedTo()
|
||||
{
|
||||
TaskDataConfig = new();
|
||||
TaskDataConfig.SaveLocation = _lastSaveLocation;
|
||||
TaskDataConfig = new()
|
||||
{
|
||||
SaveLocation = Properties.Settings.Default.DefaultSaveLocation,
|
||||
SplitCount = Properties.Settings.Default.SplitCount,
|
||||
UseParallelDownload = Properties.Settings.Default.UseParallelDownload,
|
||||
RetryCount = Properties.Settings.Default.RetryCount
|
||||
};
|
||||
}
|
||||
|
||||
public void OnNavigatedFrom()
|
||||
@@ -145,6 +149,7 @@ namespace DownloadManager.ViewModels.Pages
|
||||
ParallelDownload = TaskDataConfig.UseParallelDownload,
|
||||
MaxTryAgainOnFailover = TaskDataConfig.RetryCount,
|
||||
BufferBlockSize = 10240,
|
||||
Timeout = 1000,
|
||||
|
||||
RequestConfiguration =
|
||||
{
|
||||
@@ -155,7 +160,7 @@ namespace DownloadManager.ViewModels.Pages
|
||||
};
|
||||
|
||||
var data = new DownloadItemData(TaskDataConfig.SaveLocation, taskUrl, TaskDataConfig.UrlGetter, config);
|
||||
App.GetService<DownloaderCore.DownloadManagerService>().AddDownloadItem(data);
|
||||
downloadManager.AddDownloadItem(data);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -163,7 +168,7 @@ namespace DownloadManager.ViewModels.Pages
|
||||
|
||||
try
|
||||
{
|
||||
await App.GetService<DownloaderCore.DownloadManagerService>().FindNextDownloadAndStart();
|
||||
await downloadManager.FindNextDownloadAndStart();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -174,8 +179,6 @@ namespace DownloadManager.ViewModels.Pages
|
||||
new SymbolIcon(SymbolRegular.ErrorCircle24),
|
||||
TimeSpan.FromSeconds(5));
|
||||
}
|
||||
|
||||
_lastSaveLocation = TaskDataConfig.SaveLocation;
|
||||
}
|
||||
}
|
||||
}
|
||||
142
ViewModels/Pages/CompletedPageViewModel.cs
Normal file
142
ViewModels/Pages/CompletedPageViewModel.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
using DownloadManager.DownloaderCore;
|
||||
using DownloadManager.Models;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using Wpf.Ui;
|
||||
using Wpf.Ui.Controls;
|
||||
using Wpf.Ui.Extensions;
|
||||
|
||||
namespace DownloadManager.ViewModels.Pages
|
||||
{
|
||||
public partial class CompletedPageViewModel(DownloadManagerService downloadManager, IContentDialogService contentDialog) : ObservableObject, INavigationAware
|
||||
{
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<CompletedItemData> completedTask = new();
|
||||
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<CompletedItemData>? filteredCompletedTask;
|
||||
|
||||
private string _autoSuggestBoxText = string.Empty;
|
||||
public string AutoSuggestBoxText
|
||||
{
|
||||
get => _autoSuggestBoxText;
|
||||
set
|
||||
{
|
||||
_ = SetProperty(ref _autoSuggestBoxText, value);
|
||||
UpdateSearchResults(value);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSearchResults(string searchedText)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(searchedText))
|
||||
{
|
||||
FilteredCompletedTask = CompletedTask;
|
||||
}
|
||||
|
||||
var formattedText = searchedText.ToLower().Trim();
|
||||
|
||||
FilteredCompletedTask = new(CompletedTask
|
||||
.Where(task => task.Name.Contains(formattedText, StringComparison.OrdinalIgnoreCase)));
|
||||
});
|
||||
}
|
||||
|
||||
public void OnNavigatedFrom()
|
||||
{
|
||||
downloadManager.OnActiveWorkerChanged -= DownloadService_OnActiveWorkerChanged;
|
||||
}
|
||||
|
||||
public void OnNavigatedTo()
|
||||
{
|
||||
downloadManager.OnActiveWorkerChanged += DownloadService_OnActiveWorkerChanged;
|
||||
|
||||
LoadTasks();
|
||||
}
|
||||
|
||||
private void DownloadService_OnActiveWorkerChanged()
|
||||
{
|
||||
LoadTasks();
|
||||
}
|
||||
private void LoadTasks()
|
||||
{
|
||||
CompletedTask = new(downloadManager.GetCompletedTask());
|
||||
AutoSuggestBoxText = string.Empty;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public async Task ClearCompletedTask()
|
||||
{
|
||||
await downloadManager.ClearCompletedTask();
|
||||
LoadTasks();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private static void OpenFile(CompletedItemData completedItem)
|
||||
{
|
||||
if (!File.Exists(completedItem.FullName))
|
||||
return;
|
||||
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = completedItem.FullName,
|
||||
UseShellExecute = true
|
||||
});
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private static void OpenFolder(CompletedItemData completedItem)
|
||||
{
|
||||
if (!File.Exists(completedItem.FullName))
|
||||
return;
|
||||
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = "explorer.exe",
|
||||
Arguments = $"/select, \"{completedItem.FullName}\""
|
||||
});
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task DeleteTask(CompletedItemData completedItem)
|
||||
{
|
||||
var result = await contentDialog.ShowSimpleDialogAsync(new SimpleContentDialogCreateOptions()
|
||||
{
|
||||
Title = "Also delete downloaded file?",
|
||||
Content = "Do you want to also delete the source file?",
|
||||
PrimaryButtonText = "Yes",
|
||||
SecondaryButtonText = "No",
|
||||
CloseButtonText = "Cancel",
|
||||
});
|
||||
|
||||
await DeleteTaskAndFile(completedItem, result == ContentDialogResult.Primary);
|
||||
}
|
||||
|
||||
private async Task DeleteTaskAndFile(CompletedItemData completedItem, bool isIncludeSource)
|
||||
{
|
||||
if (isIncludeSource)
|
||||
{
|
||||
File.Delete(completedItem.FullName);
|
||||
}
|
||||
|
||||
await downloadManager.RemoveCompletedTask(completedItem);
|
||||
LoadTasks();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private static void CopyPath(CompletedItemData completedItem)
|
||||
{
|
||||
Clipboard.Clear();
|
||||
Clipboard.SetText(completedItem.FullName);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private static void CopyUrl(CompletedItemData completedItem)
|
||||
{
|
||||
Clipboard.Clear();
|
||||
Clipboard.SetText(completedItem.Url);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,18 +5,19 @@ using Wpf.Ui.Controls;
|
||||
|
||||
namespace DownloadManager.ViewModels.Pages;
|
||||
|
||||
public partial class DownloadingPageViewModel : ObservableObject, INavigationAware
|
||||
public partial class DownloadingPageViewModel(DownloadManagerService downloadManager) : ObservableObject, INavigationAware
|
||||
{
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<DownloadItemData>? downloadingTask;
|
||||
|
||||
public void OnNavigatedFrom()
|
||||
{
|
||||
downloadManager.OnActiveWorkerChanged -= DownloadService_OnDownloadServiceChanged;
|
||||
}
|
||||
|
||||
public void OnNavigatedTo()
|
||||
{
|
||||
App.GetService<DownloadManagerService>().OnActiveWorkerChanged += DownloadService_OnDownloadServiceChanged;
|
||||
downloadManager.OnActiveWorkerChanged += DownloadService_OnDownloadServiceChanged;
|
||||
|
||||
LoadTasks();
|
||||
}
|
||||
@@ -28,6 +29,6 @@ public partial class DownloadingPageViewModel : ObservableObject, INavigationAwa
|
||||
|
||||
private void LoadTasks()
|
||||
{
|
||||
DownloadingTask = new(App.GetService<DownloadManagerService>().GetDownloadingTask());
|
||||
DownloadingTask = new(downloadManager.GetDownloadingTask());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
|
||||
// All Rights Reserved.
|
||||
|
||||
using Microsoft.Win32;
|
||||
using System.Diagnostics;
|
||||
using Wpf.Ui.Appearance;
|
||||
using Wpf.Ui.Controls;
|
||||
|
||||
@@ -12,15 +14,43 @@ public partial class SettingsViewModel : ObservableObject, INavigationAware
|
||||
private bool _isInitialized = false;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _appVersion = String.Empty;
|
||||
private string _appVersion = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private ApplicationTheme _currentTheme = ApplicationTheme.Unknown;
|
||||
private ApplicationTheme _currentTheme = (ApplicationTheme)Properties.Settings.Default.Theme;
|
||||
[ObservableProperty]
|
||||
private IEnumerable<ApplicationTheme> _themes = Enum.GetValues(typeof(ApplicationTheme)).Cast<ApplicationTheme>();
|
||||
|
||||
[ObservableProperty]
|
||||
private WindowBackdropType _currentBackdrop = (WindowBackdropType)Properties.Settings.Default.Backdrop;
|
||||
[ObservableProperty]
|
||||
private IEnumerable<WindowBackdropType> _backdrops = Enum.GetValues(typeof(WindowBackdropType)).Cast<WindowBackdropType>();
|
||||
|
||||
[ObservableProperty]
|
||||
private string _defaultSaveLocation = Properties.Settings.Default.DefaultSaveLocation;
|
||||
[ObservableProperty]
|
||||
private int _splitCount = Properties.Settings.Default.SplitCount;
|
||||
[ObservableProperty]
|
||||
private bool _useParallelDownload = Properties.Settings.Default.UseParallelDownload;
|
||||
[ObservableProperty]
|
||||
private int _retryCount = Properties.Settings.Default.RetryCount;
|
||||
|
||||
public void OnNavigatedTo()
|
||||
{
|
||||
if (!_isInitialized)
|
||||
InitializeViewModel();
|
||||
|
||||
ResetOption();
|
||||
}
|
||||
|
||||
private void ResetOption()
|
||||
{
|
||||
CurrentTheme = (ApplicationTheme)Properties.Settings.Default.Theme;
|
||||
CurrentBackdrop = (WindowBackdropType)Properties.Settings.Default.Backdrop;
|
||||
DefaultSaveLocation = Properties.Settings.Default.DefaultSaveLocation;
|
||||
SplitCount = Properties.Settings.Default.SplitCount;
|
||||
UseParallelDownload = Properties.Settings.Default.UseParallelDownload;
|
||||
RetryCount = Properties.Settings.Default.RetryCount;
|
||||
}
|
||||
|
||||
public void OnNavigatedFrom()
|
||||
@@ -29,40 +59,49 @@ public partial class SettingsViewModel : ObservableObject, INavigationAware
|
||||
|
||||
private void InitializeViewModel()
|
||||
{
|
||||
CurrentTheme = ApplicationThemeManager.GetAppTheme();
|
||||
AppVersion = $"UiDesktopApp1 - {GetAssemblyVersion()}";
|
||||
|
||||
AppVersion = $"DownloadManager - {GetAssemblyVersion()}";
|
||||
_isInitialized = true;
|
||||
}
|
||||
|
||||
private string GetAssemblyVersion()
|
||||
{
|
||||
return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version?.ToString()
|
||||
?? String.Empty;
|
||||
?? string.Empty;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void OnChangeTheme(string parameter)
|
||||
private void SaveSettings()
|
||||
{
|
||||
switch (parameter)
|
||||
Properties.Settings.Default.Theme = (int)CurrentTheme;
|
||||
Properties.Settings.Default.Backdrop = (int)CurrentBackdrop;
|
||||
Properties.Settings.Default.DefaultSaveLocation = DefaultSaveLocation;
|
||||
Properties.Settings.Default.SplitCount = SplitCount;
|
||||
Properties.Settings.Default.UseParallelDownload = UseParallelDownload;
|
||||
Properties.Settings.Default.RetryCount = RetryCount;
|
||||
|
||||
ApplicationThemeManager.Apply(CurrentTheme, CurrentBackdrop);
|
||||
|
||||
Properties.Settings.Default.Save();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void ChangeSaveLocation()
|
||||
{
|
||||
OpenFolderDialog openFolderDialog = new()
|
||||
{
|
||||
case "theme_light":
|
||||
if (CurrentTheme == ApplicationTheme.Light)
|
||||
break;
|
||||
Multiselect = false,
|
||||
InitialDirectory = DefaultSaveLocation
|
||||
};
|
||||
|
||||
ApplicationThemeManager.Apply(ApplicationTheme.Light);
|
||||
CurrentTheme = ApplicationTheme.Light;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
if (CurrentTheme == ApplicationTheme.Dark)
|
||||
break;
|
||||
|
||||
ApplicationThemeManager.Apply(ApplicationTheme.Dark);
|
||||
CurrentTheme = ApplicationTheme.Dark;
|
||||
|
||||
break;
|
||||
if (openFolderDialog.ShowDialog() == true)
|
||||
{
|
||||
DefaultSaveLocation = openFolderDialog.FolderName;
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void AppUpdate()
|
||||
{
|
||||
Debug.WriteLine("AppUpdate");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,18 +5,19 @@ using Wpf.Ui.Controls;
|
||||
|
||||
namespace DownloadManager.ViewModels.Pages;
|
||||
|
||||
public partial class WaitingPageViewModel : ObservableObject, INavigationAware
|
||||
public partial class WaitingPageViewModel(DownloadManagerService downloadManager) : ObservableObject, INavigationAware
|
||||
{
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<DownloadItemData>? waitingTask;
|
||||
|
||||
public void OnNavigatedFrom()
|
||||
{
|
||||
downloadManager.OnQueuedItemChanged -= DownloadService_OnQueuedItemChanged;
|
||||
}
|
||||
|
||||
public void OnNavigatedTo()
|
||||
{
|
||||
App.GetService<DownloadManagerService>().OnQueuedItemChanged += DownloadService_OnQueuedItemChanged;
|
||||
downloadManager.OnQueuedItemChanged += DownloadService_OnQueuedItemChanged;
|
||||
|
||||
LoadTasks();
|
||||
}
|
||||
@@ -28,6 +29,6 @@ public partial class WaitingPageViewModel : ObservableObject, INavigationAware
|
||||
|
||||
private void LoadTasks()
|
||||
{
|
||||
WaitingTask = new (App.GetService<DownloadManagerService>().GetWaitingTask());
|
||||
WaitingTask = new(downloadManager.GetWaitingTask());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user