diff --git a/YoutubeDownloader.Core/Downloading/VideoDownloader.cs b/YoutubeDownloader.Core/Downloading/VideoDownloader.cs index 0632bd1b4..0a00c103f 100644 --- a/YoutubeDownloader.Core/Downloading/VideoDownloader.cs +++ b/YoutubeDownloader.Core/Downloading/VideoDownloader.cs @@ -13,12 +13,10 @@ namespace YoutubeDownloader.Core.Downloading; -public class VideoDownloader +public class VideoDownloader(IReadOnlyList? initialCookies = null) { - private readonly YoutubeClient _youtube; - - public VideoDownloader(IReadOnlyList? initialCookies = null) => - _youtube = new YoutubeClient(Http.Client, initialCookies ?? Array.Empty()); + private readonly YoutubeClient _youtube = + new(Http.Client, initialCookies ?? Array.Empty()); public async Task> GetDownloadOptionsAsync( VideoId videoId, diff --git a/YoutubeDownloader.Core/Resolving/QueryResolver.cs b/YoutubeDownloader.Core/Resolving/QueryResolver.cs index ed95f3216..65c043ad8 100644 --- a/YoutubeDownloader.Core/Resolving/QueryResolver.cs +++ b/YoutubeDownloader.Core/Resolving/QueryResolver.cs @@ -14,12 +14,10 @@ namespace YoutubeDownloader.Core.Resolving; -public class QueryResolver +public class QueryResolver(IReadOnlyList? initialCookies = null) { - private readonly YoutubeClient _youtube; - - public QueryResolver(IReadOnlyList? initialCookies = null) => - _youtube = new YoutubeClient(Http.Client, initialCookies ?? Array.Empty()); + private readonly YoutubeClient _youtube = + new(Http.Client, initialCookies ?? Array.Empty()); public async Task ResolveAsync( string query, diff --git a/YoutubeDownloader.Core/Tagging/MediaFile.cs b/YoutubeDownloader.Core/Tagging/MediaFile.cs index 4ee9562e5..38396bc5c 100644 --- a/YoutubeDownloader.Core/Tagging/MediaFile.cs +++ b/YoutubeDownloader.Core/Tagging/MediaFile.cs @@ -4,32 +4,28 @@ namespace YoutubeDownloader.Core.Tagging; -internal partial class MediaFile : IDisposable +internal partial class MediaFile(TagFile file) : IDisposable { - private readonly TagFile _file; - - public MediaFile(TagFile file) => _file = file; - public void SetThumbnail(byte[] thumbnailData) => - _file.Tag.Pictures = new IPicture[] { new Picture(thumbnailData) }; + file.Tag.Pictures = new IPicture[] { new Picture(thumbnailData) }; - public void SetArtist(string artist) => _file.Tag.Performers = new[] { artist }; + public void SetArtist(string artist) => file.Tag.Performers = new[] { artist }; - public void SetArtistSort(string artistSort) => _file.Tag.PerformersSort = new[] { artistSort }; + public void SetArtistSort(string artistSort) => file.Tag.PerformersSort = new[] { artistSort }; - public void SetTitle(string title) => _file.Tag.Title = title; + public void SetTitle(string title) => file.Tag.Title = title; - public void SetAlbum(string album) => _file.Tag.Album = album; + public void SetAlbum(string album) => file.Tag.Album = album; - public void SetDescription(string description) => _file.Tag.Description = description; + public void SetDescription(string description) => file.Tag.Description = description; - public void SetComment(string comment) => _file.Tag.Comment = comment; + public void SetComment(string comment) => file.Tag.Comment = comment; public void Dispose() { - _file.Tag.DateTagged = DateTime.Now; - _file.Save(); - _file.Dispose(); + file.Tag.DateTagged = DateTime.Now; + file.Save(); + file.Dispose(); } } diff --git a/YoutubeDownloader.Core/Utils/ThrottleLock.cs b/YoutubeDownloader.Core/Utils/ThrottleLock.cs index fa9af0ac8..f52a643db 100644 --- a/YoutubeDownloader.Core/Utils/ThrottleLock.cs +++ b/YoutubeDownloader.Core/Utils/ThrottleLock.cs @@ -4,14 +4,11 @@ namespace YoutubeDownloader.Core.Utils; -public class ThrottleLock : IDisposable +public class ThrottleLock(TimeSpan interval) : IDisposable { private readonly SemaphoreSlim _semaphore = new(1, 1); - private readonly TimeSpan _interval; private DateTimeOffset _lastRequestInstant = DateTimeOffset.MinValue; - public ThrottleLock(TimeSpan interval) => _interval = interval; - public async Task WaitAsync(CancellationToken cancellationToken = default) { await _semaphore.WaitAsync(cancellationToken); @@ -20,7 +17,7 @@ public async Task WaitAsync(CancellationToken cancellationToken = default) { var timePassedSinceLastRequest = DateTimeOffset.Now - _lastRequestInstant; - var remainingTime = _interval - timePassedSinceLastRequest; + var remainingTime = interval - timePassedSinceLastRequest; if (remainingTime > TimeSpan.Zero) await Task.Delay(remainingTime, cancellationToken); diff --git a/YoutubeDownloader/Converters/BoolToVisibilityConverter.cs b/YoutubeDownloader/Converters/BoolToVisibilityConverter.cs index 5ed61e46e..abe7faf9a 100644 --- a/YoutubeDownloader/Converters/BoolToVisibilityConverter.cs +++ b/YoutubeDownloader/Converters/BoolToVisibilityConverter.cs @@ -6,28 +6,22 @@ namespace YoutubeDownloader.Converters; [ValueConversion(typeof(bool), typeof(Visibility))] -public partial class BoolToVisibilityConverter : IValueConverter +public partial class BoolToVisibilityConverter( + Visibility trueVisibility, + Visibility falseVisibility +) : IValueConverter { - private readonly Visibility _trueVisibility; - private readonly Visibility _falseVisibility; - - public BoolToVisibilityConverter(Visibility trueVisibility, Visibility falseVisibility) - { - _trueVisibility = trueVisibility; - _falseVisibility = falseVisibility; - } - - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) => - value is true ? _trueVisibility : _falseVisibility; + public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) => + value is true ? trueVisibility : falseVisibility; public object ConvertBack( - object value, + object? value, Type targetType, - object parameter, + object? parameter, CultureInfo culture ) => value is Visibility visibility - ? visibility == _trueVisibility + ? visibility == trueVisibility : throw new NotSupportedException(); } diff --git a/YoutubeDownloader/Converters/InverseBoolConverter.cs b/YoutubeDownloader/Converters/InverseBoolConverter.cs index 9c2870392..f75db5d30 100644 --- a/YoutubeDownloader/Converters/InverseBoolConverter.cs +++ b/YoutubeDownloader/Converters/InverseBoolConverter.cs @@ -9,13 +9,13 @@ public class InverseBoolConverter : IValueConverter { public static InverseBoolConverter Instance { get; } = new(); - public object Convert(object? value, Type targetType, object parameter, CultureInfo culture) => + public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) => value is false; public object ConvertBack( object? value, Type targetType, - object parameter, + object? parameter, CultureInfo culture ) => value is false; } diff --git a/YoutubeDownloader/Converters/VideoQualityPreferenceToStringConverter.cs b/YoutubeDownloader/Converters/VideoQualityPreferenceToStringConverter.cs index d147f48a7..fe045cfa2 100644 --- a/YoutubeDownloader/Converters/VideoQualityPreferenceToStringConverter.cs +++ b/YoutubeDownloader/Converters/VideoQualityPreferenceToStringConverter.cs @@ -10,7 +10,7 @@ public class VideoQualityPreferenceToStringConverter : IValueConverter { public static VideoQualityPreferenceToStringConverter Instance { get; } = new(); - public object? Convert(object? value, Type targetType, object parameter, CultureInfo culture) + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { if (value is VideoQualityPreference preference) return preference.GetDisplayName(); @@ -21,7 +21,7 @@ public class VideoQualityPreferenceToStringConverter : IValueConverter public object ConvertBack( object? value, Type targetType, - object parameter, + object? parameter, CultureInfo culture ) => throw new NotSupportedException(); } diff --git a/YoutubeDownloader/Converters/VideoToHighestQualityThumbnailUrlConverter.cs b/YoutubeDownloader/Converters/VideoToHighestQualityThumbnailUrlConverter.cs index a5b3a8563..3791eaf77 100644 --- a/YoutubeDownloader/Converters/VideoToHighestQualityThumbnailUrlConverter.cs +++ b/YoutubeDownloader/Converters/VideoToHighestQualityThumbnailUrlConverter.cs @@ -11,13 +11,17 @@ public class VideoToHighestQualityThumbnailUrlConverter : IValueConverter { public static VideoToHighestQualityThumbnailUrlConverter Instance { get; } = new(); - public object? Convert(object? value, Type targetType, object parameter, CultureInfo culture) => - value is IVideo video ? video.Thumbnails.TryGetWithHighestResolution()?.Url : null; + public object? Convert( + object? value, + Type targetType, + object? parameter, + CultureInfo culture + ) => value is IVideo video ? video.Thumbnails.TryGetWithHighestResolution()?.Url : null; public object ConvertBack( object? value, Type targetType, - object parameter, + object? parameter, CultureInfo culture ) => throw new NotSupportedException(); } diff --git a/YoutubeDownloader/Converters/VideoToLowestQualityThumbnailUrlConverter.cs b/YoutubeDownloader/Converters/VideoToLowestQualityThumbnailUrlConverter.cs index 82855f565..9720965f0 100644 --- a/YoutubeDownloader/Converters/VideoToLowestQualityThumbnailUrlConverter.cs +++ b/YoutubeDownloader/Converters/VideoToLowestQualityThumbnailUrlConverter.cs @@ -11,13 +11,17 @@ public class VideoToLowestQualityThumbnailUrlConverter : IValueConverter { public static VideoToLowestQualityThumbnailUrlConverter Instance { get; } = new(); - public object? Convert(object? value, Type targetType, object parameter, CultureInfo culture) => - value is IVideo video ? video.Thumbnails.MinBy(t => t.Resolution.Area)?.Url : null; + public object? Convert( + object? value, + Type targetType, + object? parameter, + CultureInfo culture + ) => value is IVideo video ? video.Thumbnails.MinBy(t => t.Resolution.Area)?.Url : null; public object ConvertBack( object? value, Type targetType, - object parameter, + object? parameter, CultureInfo culture ) => throw new NotSupportedException(); } diff --git a/YoutubeDownloader/Services/SettingsService.cs b/YoutubeDownloader/Services/SettingsService.cs index cd57c0355..6ff7d1e68 100644 --- a/YoutubeDownloader/Services/SettingsService.cs +++ b/YoutubeDownloader/Services/SettingsService.cs @@ -14,7 +14,9 @@ namespace YoutubeDownloader.Services; [AddINotifyPropertyChangedInterface] -public partial class SettingsService : SettingsBase, INotifyPropertyChanged +public partial class SettingsService() + : SettingsBase(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Settings.dat")), + INotifyPropertyChanged { public bool IsUkraineSupportMessageEnabled { get; set; } = true; @@ -43,9 +45,6 @@ public partial class SettingsService : SettingsBase, INotifyPropertyChanged public VideoQualityPreference LastVideoQualityPreference { get; set; } = VideoQualityPreference.Highest; - public SettingsService() - : base(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Settings.dat")) { } - public override void Save() { // Clear the cookies if they are not supposed to be persisted diff --git a/YoutubeDownloader/Services/UpdateService.cs b/YoutubeDownloader/Services/UpdateService.cs index 2f90f21b4..3c82bb884 100644 --- a/YoutubeDownloader/Services/UpdateService.cs +++ b/YoutubeDownloader/Services/UpdateService.cs @@ -6,27 +6,20 @@ namespace YoutubeDownloader.Services; -public class UpdateService : IDisposable +public class UpdateService(SettingsService settingsService) : IDisposable { private readonly IUpdateManager _updateManager = new UpdateManager( new GithubPackageResolver("Tyrrrz", "YoutubeDownloader", "YoutubeDownloader.zip"), new ZipPackageExtractor() ); - private readonly SettingsService _settingsService; - private Version? _updateVersion; private bool _updatePrepared; private bool _updaterLaunched; - public UpdateService(SettingsService settingsService) - { - _settingsService = settingsService; - } - public async Task CheckForUpdatesAsync() { - if (!_settingsService.IsAutoUpdateEnabled) + if (!settingsService.IsAutoUpdateEnabled) return null; var check = await _updateManager.CheckForUpdatesAsync(); @@ -35,7 +28,7 @@ public UpdateService(SettingsService settingsService) public async Task PrepareUpdateAsync(Version version) { - if (!_settingsService.IsAutoUpdateEnabled) + if (!settingsService.IsAutoUpdateEnabled) return; try @@ -55,7 +48,7 @@ public async Task PrepareUpdateAsync(Version version) public void FinalizeUpdate(bool needRestart) { - if (!_settingsService.IsAutoUpdateEnabled) + if (!settingsService.IsAutoUpdateEnabled) return; if (_updateVersion is null || !_updatePrepared || _updaterLaunched) diff --git a/YoutubeDownloader/Utils/ResizableSemaphore.cs b/YoutubeDownloader/Utils/ResizableSemaphore.cs index ad0ba567f..2dde6c1ef 100644 --- a/YoutubeDownloader/Utils/ResizableSemaphore.cs +++ b/YoutubeDownloader/Utils/ResizableSemaphore.cs @@ -88,12 +88,8 @@ public void Dispose() internal partial class ResizableSemaphore { - private class AcquiredAccess : IDisposable + private class AcquiredAccess(ResizableSemaphore semaphore) : IDisposable { - private readonly ResizableSemaphore _semaphore; - - public AcquiredAccess(ResizableSemaphore semaphore) => _semaphore = semaphore; - - public void Dispose() => _semaphore.Release(); + public void Dispose() => semaphore.Release(); } } diff --git a/YoutubeDownloader/ViewModels/Dialogs/DownloadMultipleSetupViewModel.cs b/YoutubeDownloader/ViewModels/Dialogs/DownloadMultipleSetupViewModel.cs index 942960f79..bd4b6a238 100644 --- a/YoutubeDownloader/ViewModels/Dialogs/DownloadMultipleSetupViewModel.cs +++ b/YoutubeDownloader/ViewModels/Dialogs/DownloadMultipleSetupViewModel.cs @@ -13,12 +13,12 @@ namespace YoutubeDownloader.ViewModels.Dialogs; -public class DownloadMultipleSetupViewModel : DialogScreen> +public class DownloadMultipleSetupViewModel( + IViewModelFactory viewModelFactory, + DialogManager dialogManager, + SettingsService settingsService +) : DialogScreen> { - private readonly IViewModelFactory _viewModelFactory; - private readonly DialogManager _dialogManager; - private readonly SettingsService _settingsService; - public string? Title { get; set; } public IReadOnlyList? AvailableVideos { get; set; } @@ -36,21 +36,10 @@ public class DownloadMultipleSetupViewModel : DialogScreen Clipboard.SetText(Title!); @@ -59,7 +48,7 @@ public void OnViewLoaded() public void Confirm() { - var dirPath = _dialogManager.PromptDirectoryPath(); + var dirPath = dialogManager.PromptDirectoryPath(); if (string.IsNullOrWhiteSpace(dirPath)) return; @@ -71,14 +60,14 @@ public void Confirm() var baseFilePath = Path.Combine( dirPath, FileNameTemplate.Apply( - _settingsService.FileNameTemplate, + settingsService.FileNameTemplate, video, SelectedContainer, (i + 1).ToString().PadLeft(SelectedVideos.Count.ToString().Length, '0') ) ); - if (_settingsService.ShouldSkipExistingFiles && File.Exists(baseFilePath)) + if (settingsService.ShouldSkipExistingFiles && File.Exists(baseFilePath)) continue; var filePath = PathEx.EnsureUniquePath(baseFilePath); @@ -88,7 +77,7 @@ public void Confirm() File.WriteAllBytes(filePath, Array.Empty()); downloads.Add( - _viewModelFactory.CreateDownloadViewModel( + viewModelFactory.CreateDownloadViewModel( video, new VideoDownloadPreference(SelectedContainer, SelectedVideoQualityPreference), filePath @@ -96,8 +85,8 @@ public void Confirm() ); } - _settingsService.LastContainer = SelectedContainer; - _settingsService.LastVideoQualityPreference = SelectedVideoQualityPreference; + settingsService.LastContainer = SelectedContainer; + settingsService.LastVideoQualityPreference = SelectedVideoQualityPreference; Close(downloads); } diff --git a/YoutubeDownloader/ViewModels/Dialogs/DownloadSingleSetupViewModel.cs b/YoutubeDownloader/ViewModels/Dialogs/DownloadSingleSetupViewModel.cs index b980174a0..7f7c3ec61 100644 --- a/YoutubeDownloader/ViewModels/Dialogs/DownloadSingleSetupViewModel.cs +++ b/YoutubeDownloader/ViewModels/Dialogs/DownloadSingleSetupViewModel.cs @@ -12,33 +12,22 @@ namespace YoutubeDownloader.ViewModels.Dialogs; -public class DownloadSingleSetupViewModel : DialogScreen +public class DownloadSingleSetupViewModel( + IViewModelFactory viewModelFactory, + DialogManager dialogManager, + SettingsService settingsService +) : DialogScreen { - private readonly IViewModelFactory _viewModelFactory; - private readonly DialogManager _dialogManager; - private readonly SettingsService _settingsService; - public IVideo? Video { get; set; } public IReadOnlyList? AvailableDownloadOptions { get; set; } public VideoDownloadOption? SelectedDownloadOption { get; set; } - public DownloadSingleSetupViewModel( - IViewModelFactory viewModelFactory, - DialogManager dialogManager, - SettingsService settingsService - ) - { - _viewModelFactory = viewModelFactory; - _dialogManager = dialogManager; - _settingsService = settingsService; - } - public void OnViewLoaded() { SelectedDownloadOption = AvailableDownloadOptions?.FirstOrDefault( - o => o.Container == _settingsService.LastContainer + o => o.Container == settingsService.LastContainer ); } @@ -48,9 +37,9 @@ public void Confirm() { var container = SelectedDownloadOption!.Container; - var filePath = _dialogManager.PromptSaveFilePath( + var filePath = dialogManager.PromptSaveFilePath( $"{container.Name} file|*.{container.Name}", - FileNameTemplate.Apply(_settingsService.FileNameTemplate, Video!, container) + FileNameTemplate.Apply(settingsService.FileNameTemplate, Video!, container) ); if (string.IsNullOrWhiteSpace(filePath)) @@ -60,9 +49,9 @@ public void Confirm() DirectoryEx.CreateDirectoryForFile(filePath); File.WriteAllBytes(filePath, Array.Empty()); - _settingsService.LastContainer = container; + settingsService.LastContainer = container; - Close(_viewModelFactory.CreateDownloadViewModel(Video!, SelectedDownloadOption!, filePath)); + Close(viewModelFactory.CreateDownloadViewModel(Video!, SelectedDownloadOption!, filePath)); } } diff --git a/YoutubeDownloader/ViewModels/Dialogs/SettingsViewModel.cs b/YoutubeDownloader/ViewModels/Dialogs/SettingsViewModel.cs index 25de8596b..0974d566c 100644 --- a/YoutubeDownloader/ViewModels/Dialogs/SettingsViewModel.cs +++ b/YoutubeDownloader/ViewModels/Dialogs/SettingsViewModel.cs @@ -4,51 +4,47 @@ namespace YoutubeDownloader.ViewModels.Dialogs; -public class SettingsViewModel : DialogScreen +public class SettingsViewModel(SettingsService settingsService) : DialogScreen { - private readonly SettingsService _settingsService; - public bool IsAutoUpdateEnabled { - get => _settingsService.IsAutoUpdateEnabled; - set => _settingsService.IsAutoUpdateEnabled = value; + get => settingsService.IsAutoUpdateEnabled; + set => settingsService.IsAutoUpdateEnabled = value; } public bool IsDarkModeEnabled { - get => _settingsService.IsDarkModeEnabled; - set => _settingsService.IsDarkModeEnabled = value; + get => settingsService.IsDarkModeEnabled; + set => settingsService.IsDarkModeEnabled = value; } public bool IsAuthPersisted { - get => _settingsService.IsAuthPersisted; - set => _settingsService.IsAuthPersisted = value; + get => settingsService.IsAuthPersisted; + set => settingsService.IsAuthPersisted = value; } public bool ShouldInjectTags { - get => _settingsService.ShouldInjectTags; - set => _settingsService.ShouldInjectTags = value; + get => settingsService.ShouldInjectTags; + set => settingsService.ShouldInjectTags = value; } public bool ShouldSkipExistingFiles { - get => _settingsService.ShouldSkipExistingFiles; - set => _settingsService.ShouldSkipExistingFiles = value; + get => settingsService.ShouldSkipExistingFiles; + set => settingsService.ShouldSkipExistingFiles = value; } public string FileNameTemplate { - get => _settingsService.FileNameTemplate; - set => _settingsService.FileNameTemplate = value; + get => settingsService.FileNameTemplate; + set => settingsService.FileNameTemplate = value; } public int ParallelLimit { - get => _settingsService.ParallelLimit; - set => _settingsService.ParallelLimit = Math.Clamp(value, 1, 10); + get => settingsService.ParallelLimit; + set => settingsService.ParallelLimit = Math.Clamp(value, 1, 10); } - - public SettingsViewModel(SettingsService settingsService) => _settingsService = settingsService; } diff --git a/YoutubeDownloader/ViewModels/Framework/DialogManager.cs b/YoutubeDownloader/ViewModels/Framework/DialogManager.cs index 97943b826..3716dfd44 100644 --- a/YoutubeDownloader/ViewModels/Framework/DialogManager.cs +++ b/YoutubeDownloader/ViewModels/Framework/DialogManager.cs @@ -8,19 +8,13 @@ namespace YoutubeDownloader.ViewModels.Framework; -public class DialogManager : IDisposable +public class DialogManager(IViewManager viewManager) : IDisposable { - private readonly IViewManager _viewManager; private readonly SemaphoreSlim _dialogLock = new(1, 1); - public DialogManager(IViewManager viewManager) - { - _viewManager = viewManager; - } - public async ValueTask ShowDialogAsync(DialogScreen dialogScreen) { - var view = _viewManager.CreateAndBindViewForModelIfNecessary(dialogScreen); + var view = viewManager.CreateAndBindViewForModelIfNecessary(dialogScreen); void OnDialogOpened(object? openSender, DialogOpenedEventArgs openArgs) {