diff --git a/CRD/Downloader/Crunchyroll/CrunchyrollManager.cs b/CRD/Downloader/Crunchyroll/CrunchyrollManager.cs index 2f91ddc..ad1b08e 100644 --- a/CRD/Downloader/Crunchyroll/CrunchyrollManager.cs +++ b/CRD/Downloader/Crunchyroll/CrunchyrollManager.cs @@ -642,12 +642,20 @@ public class CrunchyrollManager{ Console.WriteLine($"Selecting stream with {Languages.Locale2language(options.Hslang).Language} hardsubs"); streams = streams.Where((s) => s.HardsubLang != "-" && s.HardsubLang == options.Hslang).ToList(); } else{ - Console.WriteLine($"Selected stream with {Languages.Locale2language(options.Hslang).Language} hardsubs not available"); + Console.Error.WriteLine($"Selected stream with {Languages.Locale2language(options.Hslang).Language} hardsubs not available"); if (hsLangs.Count > 0){ - Console.WriteLine("Try hardsubs stream: " + string.Join(", ", hsLangs)); + Console.Error.WriteLine("Try hardsubs stream: " + string.Join(", ", hsLangs)); } dlFailed = true; + + return new DownloadResponse{ + Data = new List(), + Error = dlFailed, + FileName = "./unknown", + ErrorText = "Hardsubs not available" + }; + } } else{ streams = streams.Where((s) => { @@ -659,9 +667,9 @@ public class CrunchyrollManager{ }).ToList(); if (streams.Count < 1){ - Console.WriteLine("Raw streams not available!"); + Console.Error.WriteLine("Raw streams not available!"); if (hsLangs.Count > 0){ - Console.WriteLine("Try hardsubs stream: " + string.Join(", ", hsLangs)); + Console.Error.WriteLine("Try hardsubs stream: " + string.Join(", ", hsLangs)); } dlFailed = true; @@ -776,7 +784,7 @@ public class CrunchyrollManager{ } if (chosenVideoQuality > videos.Count){ - Console.WriteLine($"The requested quality of {chosenVideoQuality} is greater than the maximum {videos.Count}.\n[WARN] Therefore, the maximum will be capped at {videos.Count}."); + Console.Error.WriteLine($"The requested quality of {chosenVideoQuality} is greater than the maximum {videos.Count}.\n[WARN] Therefore, the maximum will be capped at {videos.Count}."); chosenVideoQuality = videos.Count; } diff --git a/CRD/ViewModels/AddDownloadPageViewModel.cs b/CRD/ViewModels/AddDownloadPageViewModel.cs index 14b1f4d..eb1f4e5 100644 --- a/CRD/ViewModels/AddDownloadPageViewModel.cs +++ b/CRD/ViewModels/AddDownloadPageViewModel.cs @@ -18,6 +18,7 @@ using CRD.Utils; using CRD.Utils.Structs; using CRD.Views; using DynamicData; +using FluentAvalonia.Core; using ReactiveUI; @@ -25,31 +26,37 @@ namespace CRD.ViewModels; public partial class AddDownloadPageViewModel : ViewModelBase{ [ObservableProperty] - public string _urlInput = ""; + private string _urlInput = ""; [ObservableProperty] - public string _buttonText = "Enter Url"; + private string _buttonText = "Enter Url"; [ObservableProperty] - public bool _addAllEpisodes = false; + private string _buttonTextSelectSeason = "Select Season"; [ObservableProperty] - public bool _buttonEnabled = false; + private bool _addAllEpisodes = false; [ObservableProperty] - public bool _allButtonEnabled = false; + private bool _buttonEnabled = false; [ObservableProperty] - public bool _showLoading = false; + private bool _allButtonEnabled = false; [ObservableProperty] - public bool _searchEnabled = false; + private bool _showLoading = false; [ObservableProperty] - public bool _searchVisible = true; + private bool _searchEnabled = false; [ObservableProperty] - public bool _searchPopupVisible = false; + private bool _searchVisible = true; + + [ObservableProperty] + private bool _slectSeasonVisible = false; + + [ObservableProperty] + private bool _searchPopupVisible = false; public ObservableCollection Items{ get; } = new(); public ObservableCollection SearchItems{ get; set; } = new(); @@ -69,6 +76,8 @@ public partial class AddDownloadPageViewModel : ViewModelBase{ private CrunchySeriesList? currentSeriesList; + private bool CurrentSeasonFullySelected = false; + private readonly SemaphoreSlim _updateSearchSemaphore = new SemaphoreSlim(1, 1); public AddDownloadPageViewModel(){ @@ -93,6 +102,7 @@ public partial class AddDownloadPageViewModel : ViewModelBase{ SearchItems.Add(episode); } + SearchPopupVisible = true; RaisePropertyChanged(nameof(SearchItems)); RaisePropertyChanged(nameof(SearchVisible)); @@ -117,19 +127,23 @@ public partial class AddDownloadPageViewModel : ViewModelBase{ ButtonText = "Add Episode to Queue"; ButtonEnabled = true; SearchVisible = false; + SlectSeasonVisible = false; } else if (UrlInput.Contains("/series/")){ //Series ButtonText = "List Episodes"; ButtonEnabled = true; SearchVisible = false; + SlectSeasonVisible = false; } else{ ButtonEnabled = false; SearchVisible = true; + SlectSeasonVisible = false; } } else{ ButtonText = "Enter Url"; ButtonEnabled = false; SearchVisible = true; + SlectSeasonVisible = false; } } @@ -173,6 +187,7 @@ public partial class AddDownloadPageViewModel : ViewModelBase{ ButtonText = "Enter Url"; ButtonEnabled = false; SearchVisible = true; + SlectSeasonVisible = false; } else if (UrlInput.Length > 9){ episodesBySeason.Clear(); SeasonList.Clear(); @@ -233,6 +248,7 @@ public partial class AddDownloadPageViewModel : ViewModelBase{ CurrentSelectedSeason = SeasonList[0]; ButtonEnabled = false; AllButtonEnabled = true; + SlectSeasonVisible = true; ButtonText = "Select Episodes"; } else{ ButtonEnabled = true; @@ -244,6 +260,28 @@ public partial class AddDownloadPageViewModel : ViewModelBase{ } } + [RelayCommand] + public void OnSelectSeasonPressed(){ + if (CurrentSeasonFullySelected){ + foreach (var item in Items){ + selectedEpisodes.Remove(item.AbsolutNum); + SelectedItems.Remove(item); + } + + ButtonTextSelectSeason = "Select Season"; + } else{ + var selectedItemsSet = new HashSet(SelectedItems); + + foreach (var item in Items){ + if (selectedItemsSet.Add(item)){ + SelectedItems.Add(item); + } + } + + ButtonTextSelectSeason = "Deselect Season"; + } + } + partial void OnCurrentSelectedSeasonChanging(ComboBoxItem? oldValue, ComboBoxItem newValue){ foreach (var selectedItem in SelectedItems){ if (!selectedEpisodes.Contains(selectedItem.AbsolutNum)){ @@ -261,6 +299,14 @@ public partial class AddDownloadPageViewModel : ViewModelBase{ } private void OnSelectedItemsChanged(object? sender, NotifyCollectionChangedEventArgs e){ + CurrentSeasonFullySelected = Items.All(item => SelectedItems.Contains(item)); + + if (CurrentSeasonFullySelected){ + ButtonTextSelectSeason = "Deselect Season"; + } else{ + ButtonTextSelectSeason = "Select Season"; + } + if (selectedEpisodes.Count > 0 || SelectedItems.Count > 0 || AddAllEpisodes){ ButtonText = "Add Episodes to Queue"; ButtonEnabled = true; @@ -289,6 +335,7 @@ public partial class AddDownloadPageViewModel : ViewModelBase{ RaisePropertyChanged(nameof(SearchVisible)); SearchItems.Clear(); SearchVisible = false; + SlectSeasonVisible = true; ButtonEnabled = false; ShowLoading = true; var list = await CrunchyrollManager.Instance.CrSeries.ListSeriesId(value.Id, @@ -341,6 +388,14 @@ public partial class AddDownloadPageViewModel : ViewModelBase{ } } } + + CurrentSeasonFullySelected = Items.All(item => SelectedItems.Contains(item)); + + if (CurrentSeasonFullySelected){ + ButtonTextSelectSeason = "Deselect Season"; + } else{ + ButtonTextSelectSeason = "Select Season"; + } } } diff --git a/CRD/ViewModels/HistoryPageViewModel.cs b/CRD/ViewModels/HistoryPageViewModel.cs index 354aa4f..e4f7872 100644 --- a/CRD/ViewModels/HistoryPageViewModel.cs +++ b/CRD/ViewModels/HistoryPageViewModel.cs @@ -319,6 +319,27 @@ public partial class HistoryPageViewModel : ViewModelBase{ } } } + + [RelayCommand] + public async Task DownloadSeasonAll(HistorySeason season){ + foreach (var historyEpisode in season.EpisodesList){ + await historyEpisode.DownloadEpisode(); + } + } + + [RelayCommand] + public async Task DownloadSeasonMissing(HistorySeason season){ + foreach (var historyEpisode in season.EpisodesList.Where(historyEpisode => !historyEpisode.WasDownloaded)){ + await historyEpisode.DownloadEpisode(); + } + } + + [RelayCommand] + public async Task DownloadSeasonMissingSonarr(HistorySeason season){ + foreach (var historyEpisode in season.EpisodesList.Where(historyEpisode => !historyEpisode.SonarrHasFile)){ + await historyEpisode.DownloadEpisode(); + } + } public void SetStorageProvider(IStorageProvider storageProvider){ diff --git a/CRD/ViewModels/SeriesPageViewModel.cs b/CRD/ViewModels/SeriesPageViewModel.cs index e238731..cea88f2 100644 --- a/CRD/ViewModels/SeriesPageViewModel.cs +++ b/CRD/ViewModels/SeriesPageViewModel.cs @@ -28,10 +28,6 @@ public partial class SeriesPageViewModel : ViewModelBase{ [ObservableProperty] public static bool _sonarrAvailable; - - - - private IStorageProvider? _storageProvider; public SeriesPageViewModel(){ @@ -84,6 +80,27 @@ public partial class SeriesPageViewModel : ViewModelBase{ } + [RelayCommand] + public async Task DownloadSeasonAll(HistorySeason season){ + foreach (var historyEpisode in season.EpisodesList){ + await historyEpisode.DownloadEpisode(); + } + } + + [RelayCommand] + public async Task DownloadSeasonMissing(HistorySeason season){ + foreach (var historyEpisode in season.EpisodesList.Where(historyEpisode => !historyEpisode.WasDownloaded)){ + await historyEpisode.DownloadEpisode(); + } + } + + [RelayCommand] + public async Task DownloadSeasonMissingSonarr(HistorySeason season){ + foreach (var historyEpisode in season.EpisodesList.Where(historyEpisode => !historyEpisode.SonarrHasFile)){ + await historyEpisode.DownloadEpisode(); + } + } + [RelayCommand] public async Task UpdateData(string? season){ await SelectedSeries.FetchData(season); diff --git a/CRD/Views/AddDownloadPageView.axaml b/CRD/Views/AddDownloadPageView.axaml index 4f7afd1..00683ec 100644 --- a/CRD/Views/AddDownloadPageView.axaml +++ b/CRD/Views/AddDownloadPageView.axaml @@ -115,6 +115,10 @@ + + diff --git a/CRD/Views/HistoryPageView.axaml b/CRD/Views/HistoryPageView.axaml index 42268b9..cf970f0 100644 --- a/CRD/Views/HistoryPageView.axaml +++ b/CRD/Views/HistoryPageView.axaml @@ -237,14 +237,13 @@ - @@ -516,8 +515,7 @@ - + IsVisible="{Binding $parent[ScrollViewer].((history:HistorySeries)DataContext).SonarrSeriesId, Converter={StaticResource UiSonarrIdToVisibilityConverter}}"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +