2024-06-29 20:15:34 +00:00
|
|
|
using System;
|
2024-08-05 03:06:40 +00:00
|
|
|
using System.Collections.Concurrent;
|
|
|
|
using System.Collections.Generic;
|
2024-05-04 15:35:32 +00:00
|
|
|
using System.Collections.ObjectModel;
|
2024-06-26 22:04:50 +00:00
|
|
|
using System.Globalization;
|
2024-05-04 15:35:32 +00:00
|
|
|
using System.Linq;
|
2024-06-26 22:04:50 +00:00
|
|
|
using System.Reflection;
|
|
|
|
using System.Runtime.Serialization;
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
using Avalonia;
|
|
|
|
using Avalonia.Controls;
|
|
|
|
using Avalonia.Platform.Storage;
|
2024-07-12 13:53:44 +00:00
|
|
|
using Avalonia.Threading;
|
2024-05-04 15:35:32 +00:00
|
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
|
|
using CommunityToolkit.Mvvm.Input;
|
|
|
|
using CRD.Downloader;
|
2024-07-21 09:30:20 +00:00
|
|
|
using CRD.Downloader.Crunchyroll;
|
2024-05-11 11:08:24 +00:00
|
|
|
using CRD.Utils;
|
2024-08-05 03:06:40 +00:00
|
|
|
using CRD.Utils.Sonarr;
|
2024-06-26 22:04:50 +00:00
|
|
|
using CRD.Utils.Structs;
|
|
|
|
using CRD.Utils.Structs.History;
|
2024-05-04 15:35:32 +00:00
|
|
|
using CRD.Views;
|
2024-06-26 22:04:50 +00:00
|
|
|
using DynamicData;
|
2024-08-05 03:06:40 +00:00
|
|
|
using HarfBuzzSharp;
|
2024-05-04 15:35:32 +00:00
|
|
|
using ReactiveUI;
|
|
|
|
|
|
|
|
namespace CRD.ViewModels;
|
|
|
|
|
|
|
|
public partial class HistoryPageViewModel : ViewModelBase{
|
|
|
|
public ObservableCollection<HistorySeries> Items{ get; }
|
2024-08-05 03:06:40 +00:00
|
|
|
public ObservableCollection<HistorySeries> FilteredItems{ get; }
|
2024-05-11 11:08:24 +00:00
|
|
|
|
|
|
|
[ObservableProperty]
|
2024-06-11 21:58:44 +00:00
|
|
|
private static bool _fetchingData;
|
2024-05-11 11:08:24 +00:00
|
|
|
|
2024-05-04 15:35:32 +00:00
|
|
|
[ObservableProperty]
|
2024-08-05 03:06:40 +00:00
|
|
|
private HistorySeries _selectedSeries;
|
2024-05-04 15:35:32 +00:00
|
|
|
|
2024-05-11 11:08:24 +00:00
|
|
|
[ObservableProperty]
|
2024-08-05 03:06:40 +00:00
|
|
|
private static bool _editMode;
|
2024-05-11 11:08:24 +00:00
|
|
|
|
2024-06-26 22:04:50 +00:00
|
|
|
[ObservableProperty]
|
2024-08-05 03:06:40 +00:00
|
|
|
private double _scaleValue;
|
2024-06-26 22:04:50 +00:00
|
|
|
|
|
|
|
[ObservableProperty]
|
2024-08-05 03:06:40 +00:00
|
|
|
private ComboBoxItem? _selectedView;
|
2024-06-26 22:04:50 +00:00
|
|
|
|
|
|
|
public ObservableCollection<ComboBoxItem> ViewsList{ get; } =[];
|
|
|
|
|
|
|
|
[ObservableProperty]
|
2024-08-05 03:06:40 +00:00
|
|
|
private SortingListElement? _selectedSorting;
|
2024-06-26 22:04:50 +00:00
|
|
|
|
2024-07-12 13:53:44 +00:00
|
|
|
public ObservableCollection<SortingListElement> SortingList{ get; } =[];
|
2024-06-26 22:04:50 +00:00
|
|
|
|
|
|
|
[ObservableProperty]
|
2024-08-05 03:06:40 +00:00
|
|
|
private FilterListElement? _selectedFilter;
|
|
|
|
|
|
|
|
public ObservableCollection<FilterListElement> FilterList{ get; } =[];
|
|
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
private double _posterWidth;
|
2024-06-26 22:04:50 +00:00
|
|
|
|
|
|
|
[ObservableProperty]
|
2024-08-05 03:06:40 +00:00
|
|
|
private double _posterHeight;
|
2024-06-26 22:04:50 +00:00
|
|
|
|
|
|
|
[ObservableProperty]
|
2024-08-05 03:06:40 +00:00
|
|
|
private double _posterImageWidth;
|
2024-06-26 22:04:50 +00:00
|
|
|
|
|
|
|
[ObservableProperty]
|
2024-08-05 03:06:40 +00:00
|
|
|
private double _posterImageHeight;
|
2024-06-26 22:04:50 +00:00
|
|
|
|
|
|
|
[ObservableProperty]
|
2024-08-05 03:06:40 +00:00
|
|
|
private double _posterTextSize;
|
2024-06-26 22:04:50 +00:00
|
|
|
|
|
|
|
[ObservableProperty]
|
2024-08-05 03:06:40 +00:00
|
|
|
private Thickness _cornerMargin;
|
2024-06-26 22:04:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
[ObservableProperty]
|
2024-08-05 03:06:40 +00:00
|
|
|
private bool _isPosterViewSelected = false;
|
|
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
private bool _isTableViewSelected = false;
|
2024-06-26 22:04:50 +00:00
|
|
|
|
|
|
|
[ObservableProperty]
|
2024-08-05 03:06:40 +00:00
|
|
|
private static bool _viewSelectionOpen;
|
2024-06-26 22:04:50 +00:00
|
|
|
|
|
|
|
[ObservableProperty]
|
2024-08-05 03:06:40 +00:00
|
|
|
private static bool _sortingSelectionOpen;
|
2024-06-26 22:04:50 +00:00
|
|
|
|
|
|
|
[ObservableProperty]
|
2024-08-05 03:06:40 +00:00
|
|
|
private static bool _addingMissingSonarrSeries;
|
|
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
private static bool _sonarrOptionsOpen;
|
2024-06-26 22:04:50 +00:00
|
|
|
|
|
|
|
private IStorageProvider _storageProvider;
|
|
|
|
|
2024-08-05 03:06:40 +00:00
|
|
|
private HistoryViewType currentViewType;
|
|
|
|
|
|
|
|
private SortingType currentSortingType;
|
|
|
|
|
|
|
|
private FilterType currentFilterType;
|
2024-06-26 22:04:50 +00:00
|
|
|
|
2024-07-12 13:53:44 +00:00
|
|
|
[ObservableProperty]
|
2024-08-05 03:06:40 +00:00
|
|
|
private static bool _sortDir = false;
|
|
|
|
|
|
|
|
[ObservableProperty]
|
|
|
|
private static bool _sonarrAvailable;
|
2024-07-16 23:52:46 +00:00
|
|
|
|
2024-08-05 03:06:40 +00:00
|
|
|
[ObservableProperty]
|
|
|
|
private static string _progressText;
|
|
|
|
|
2024-05-04 15:35:32 +00:00
|
|
|
public HistoryPageViewModel(){
|
2024-08-05 03:06:40 +00:00
|
|
|
if (CrunchyrollManager.Instance.CrunOptions.SonarrProperties != null){
|
|
|
|
SonarrAvailable = CrunchyrollManager.Instance.CrunOptions.SonarrProperties.SonarrEnabled;
|
|
|
|
} else{
|
|
|
|
SonarrAvailable = false;
|
|
|
|
}
|
|
|
|
|
2024-07-21 09:30:20 +00:00
|
|
|
Items = CrunchyrollManager.Instance.HistoryList;
|
2024-08-05 03:06:40 +00:00
|
|
|
FilteredItems = new ObservableCollection<HistorySeries>();
|
2024-05-11 11:08:24 +00:00
|
|
|
|
2024-07-21 09:30:20 +00:00
|
|
|
HistoryPageProperties? properties = CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties;
|
2024-06-26 22:04:50 +00:00
|
|
|
|
|
|
|
currentViewType = properties?.SelectedView ?? HistoryViewType.Posters;
|
|
|
|
currentSortingType = properties?.SelectedSorting ?? SortingType.SeriesTitle;
|
2024-08-05 03:06:40 +00:00
|
|
|
currentFilterType = properties?.SelectedFilter ?? FilterType.All;
|
2024-06-26 22:04:50 +00:00
|
|
|
ScaleValue = properties?.ScaleValue ?? 0.73;
|
2024-07-12 13:53:44 +00:00
|
|
|
SortDir = properties?.Ascending ?? false;
|
2024-06-26 22:04:50 +00:00
|
|
|
|
|
|
|
foreach (HistoryViewType viewType in Enum.GetValues(typeof(HistoryViewType))){
|
|
|
|
var combobox = new ComboBoxItem{ Content = viewType };
|
|
|
|
ViewsList.Add(combobox);
|
|
|
|
if (viewType == currentViewType){
|
|
|
|
SelectedView = combobox;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach (SortingType sortingType in Enum.GetValues(typeof(SortingType))){
|
2024-07-12 13:53:44 +00:00
|
|
|
var combobox = new SortingListElement(){ SortingTitle = sortingType.GetEnumMemberValue(), SelectedSorting = sortingType };
|
2024-06-26 22:04:50 +00:00
|
|
|
SortingList.Add(combobox);
|
|
|
|
if (sortingType == currentSortingType){
|
|
|
|
SelectedSorting = combobox;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-05 03:06:40 +00:00
|
|
|
foreach (FilterType filterType in Enum.GetValues(typeof(FilterType))){
|
|
|
|
|
|
|
|
if (!SonarrAvailable && (filterType == FilterType.MissingEpisodesSonarr || filterType == FilterType.ContinuingOnly)){
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
var item = new FilterListElement(){ FilterTitle = filterType.GetEnumMemberValue(), SelectedType = filterType };
|
|
|
|
FilterList.Add(item);
|
|
|
|
if (filterType == currentFilterType){
|
|
|
|
SelectedFilter = item;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-26 22:04:50 +00:00
|
|
|
IsPosterViewSelected = currentViewType == HistoryViewType.Posters;
|
|
|
|
IsTableViewSelected = currentViewType == HistoryViewType.Table;
|
|
|
|
|
|
|
|
|
2024-05-04 15:35:32 +00:00
|
|
|
foreach (var historySeries in Items){
|
|
|
|
if (historySeries.ThumbnailImage == null){
|
|
|
|
historySeries.LoadImage();
|
|
|
|
}
|
2024-05-11 11:08:24 +00:00
|
|
|
|
2024-05-04 15:35:32 +00:00
|
|
|
historySeries.UpdateNewEpisodes();
|
|
|
|
}
|
2024-06-26 22:04:50 +00:00
|
|
|
|
2024-07-21 09:30:20 +00:00
|
|
|
CrunchyrollManager.Instance.History.SortItems();
|
2024-06-26 22:04:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void UpdateSettings(){
|
2024-07-21 09:30:20 +00:00
|
|
|
if (CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties != null){
|
|
|
|
CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.ScaleValue = ScaleValue;
|
|
|
|
CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.SelectedView = currentViewType;
|
|
|
|
CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.SelectedSorting = currentSortingType;
|
2024-06-26 22:04:50 +00:00
|
|
|
} else{
|
2024-07-21 09:30:20 +00:00
|
|
|
CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties = new HistoryPageProperties(){ ScaleValue = ScaleValue, SelectedView = currentViewType, SelectedSorting = currentSortingType };
|
2024-06-26 22:04:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CfgManager.WriteSettingsToFile();
|
|
|
|
}
|
|
|
|
|
|
|
|
partial void OnSelectedViewChanged(ComboBoxItem value){
|
|
|
|
if (Enum.TryParse(value.Content + "", out HistoryViewType viewType)){
|
|
|
|
currentViewType = viewType;
|
|
|
|
IsPosterViewSelected = currentViewType == HistoryViewType.Posters;
|
|
|
|
IsTableViewSelected = currentViewType == HistoryViewType.Table;
|
|
|
|
} else{
|
|
|
|
Console.Error.WriteLine("Invalid viewtype selected");
|
|
|
|
}
|
|
|
|
|
|
|
|
ViewSelectionOpen = false;
|
|
|
|
UpdateSettings();
|
|
|
|
}
|
|
|
|
|
2024-07-12 13:53:44 +00:00
|
|
|
|
|
|
|
partial void OnSelectedSortingChanged(SortingListElement? oldValue, SortingListElement? newValue){
|
|
|
|
if (newValue == null){
|
2024-07-21 09:30:20 +00:00
|
|
|
if (CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties != null){
|
|
|
|
CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.Ascending = !CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.Ascending;
|
|
|
|
SortDir = CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.Ascending;
|
2024-07-12 13:53:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Dispatcher.UIThread.InvokeAsync(() => {
|
|
|
|
SelectedSorting = oldValue ?? SortingList.First();
|
|
|
|
RaisePropertyChanged(nameof(SelectedSorting));
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newValue.SelectedSorting != null){
|
|
|
|
currentSortingType = newValue.SelectedSorting;
|
2024-07-21 09:30:20 +00:00
|
|
|
if (CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties != null) CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.SelectedSorting = currentSortingType;
|
|
|
|
CrunchyrollManager.Instance.History.SortItems();
|
2024-08-05 03:06:40 +00:00
|
|
|
if (SelectedFilter != null){
|
|
|
|
OnSelectedFilterChanged(SelectedFilter);
|
|
|
|
}
|
|
|
|
|
2024-06-26 22:04:50 +00:00
|
|
|
} else{
|
|
|
|
Console.Error.WriteLine("Invalid viewtype selected");
|
|
|
|
}
|
|
|
|
|
|
|
|
SortingSelectionOpen = false;
|
|
|
|
UpdateSettings();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-08-05 03:06:40 +00:00
|
|
|
partial void OnSelectedFilterChanged(FilterListElement? value){
|
|
|
|
|
|
|
|
if (value == null){
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
currentFilterType = value.SelectedType;
|
|
|
|
if (CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties != null) CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.SelectedFilter = currentFilterType;
|
|
|
|
|
|
|
|
|
|
|
|
switch (currentFilterType){
|
|
|
|
case FilterType.All:
|
|
|
|
FilteredItems.Clear();
|
|
|
|
FilteredItems.AddRange(Items);
|
|
|
|
break;
|
|
|
|
case FilterType.MissingEpisodes:
|
|
|
|
List<HistorySeries> filteredItems = Items.Where(item => item.NewEpisodes > 0).ToList();
|
|
|
|
FilteredItems.Clear();
|
|
|
|
FilteredItems.AddRange(filteredItems);
|
|
|
|
break;
|
|
|
|
case FilterType.MissingEpisodesSonarr:
|
|
|
|
|
|
|
|
var missingSonarrFiltered = Items.Where(historySeries =>
|
|
|
|
!string.IsNullOrEmpty(historySeries.SonarrSeriesId) && // Check series ID
|
|
|
|
historySeries.Seasons.Any(season => // Check each season
|
|
|
|
season.EpisodesList.Any(historyEpisode => // Check each episode
|
|
|
|
!string.IsNullOrEmpty(historyEpisode.SonarrEpisodeId) && !historyEpisode.SonarrHasFile))) // Filter condition
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
FilteredItems.Clear();
|
|
|
|
FilteredItems.AddRange(missingSonarrFiltered);
|
|
|
|
|
|
|
|
break;
|
|
|
|
case FilterType.ContinuingOnly:
|
|
|
|
List<HistorySeries> continuingFiltered = Items.Where(item => !string.IsNullOrEmpty(item.SonarrNextAirDate)).ToList();
|
|
|
|
FilteredItems.Clear();
|
|
|
|
FilteredItems.AddRange(continuingFiltered);
|
|
|
|
break;
|
|
|
|
}
|
2024-05-04 15:35:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-06-26 22:04:50 +00:00
|
|
|
partial void OnScaleValueChanged(double value){
|
|
|
|
double t = (ScaleValue - 0.5) / (1 - 0.5);
|
|
|
|
|
|
|
|
PosterHeight = Math.Clamp(225 + t * (410 - 225), 225, 410);
|
|
|
|
PosterWidth = 250 * ScaleValue;
|
|
|
|
PosterImageHeight = 360 * ScaleValue;
|
|
|
|
PosterImageWidth = 240 * ScaleValue;
|
|
|
|
|
|
|
|
|
|
|
|
double posterTextSizeCalc = 11 + t * (15 - 11);
|
|
|
|
|
|
|
|
PosterTextSize = Math.Clamp(posterTextSizeCalc, 11, 15);
|
|
|
|
CornerMargin = new Thickness(0, 0, Math.Clamp(3 + t * (5 - 3), 3, 5), 0);
|
|
|
|
UpdateSettings();
|
|
|
|
}
|
2024-06-11 21:58:44 +00:00
|
|
|
|
|
|
|
|
2024-05-04 15:35:32 +00:00
|
|
|
partial void OnSelectedSeriesChanged(HistorySeries value){
|
2024-07-21 09:30:20 +00:00
|
|
|
CrunchyrollManager.Instance.SelectedSeries = value;
|
2024-06-26 22:04:50 +00:00
|
|
|
|
2024-06-28 03:28:45 +00:00
|
|
|
NavToSeries();
|
2024-07-12 13:53:44 +00:00
|
|
|
|
2024-07-21 09:30:20 +00:00
|
|
|
if (!string.IsNullOrEmpty(value.SonarrSeriesId) && CrunchyrollManager.Instance.CrunOptions.SonarrProperties is{ SonarrEnabled: true }){
|
|
|
|
CrunchyrollManager.Instance.History.MatchHistoryEpisodesWithSonarr(true, SelectedSeries);
|
2024-06-26 22:04:50 +00:00
|
|
|
}
|
|
|
|
|
2024-07-12 13:53:44 +00:00
|
|
|
|
2024-05-04 15:35:32 +00:00
|
|
|
_selectedSeries = null;
|
|
|
|
}
|
2024-06-11 21:58:44 +00:00
|
|
|
|
2024-05-11 11:08:24 +00:00
|
|
|
[RelayCommand]
|
|
|
|
public void RemoveSeries(string? seriesId){
|
2024-07-21 09:30:20 +00:00
|
|
|
HistorySeries? objectToRemove = CrunchyrollManager.Instance.HistoryList.ToList().Find(se => se.SeriesId == seriesId) ?? null;
|
2024-06-11 21:58:44 +00:00
|
|
|
if (objectToRemove != null){
|
2024-07-21 09:30:20 +00:00
|
|
|
CrunchyrollManager.Instance.HistoryList.Remove(objectToRemove);
|
2024-05-11 11:08:24 +00:00
|
|
|
Items.Remove(objectToRemove);
|
2024-08-05 03:06:40 +00:00
|
|
|
FilteredItems.Remove(objectToRemove);
|
2024-07-16 23:52:46 +00:00
|
|
|
CfgManager.UpdateHistoryFile();
|
2024-05-11 11:08:24 +00:00
|
|
|
}
|
|
|
|
}
|
2024-06-11 21:58:44 +00:00
|
|
|
|
2024-05-04 15:35:32 +00:00
|
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
public void NavToSeries(){
|
2024-06-11 21:58:44 +00:00
|
|
|
if (FetchingData){
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-05-11 11:08:24 +00:00
|
|
|
MessageBus.Current.SendMessage(new NavigationMessage(typeof(SeriesPageViewModel), false, false));
|
2024-05-04 15:35:32 +00:00
|
|
|
}
|
2024-05-11 11:08:24 +00:00
|
|
|
|
2024-05-04 15:35:32 +00:00
|
|
|
[RelayCommand]
|
2024-08-05 03:06:40 +00:00
|
|
|
public async Task RefreshAll(){
|
2024-06-11 21:58:44 +00:00
|
|
|
FetchingData = true;
|
|
|
|
RaisePropertyChanged(nameof(FetchingData));
|
2024-08-05 03:06:40 +00:00
|
|
|
foreach (var item in FilteredItems){
|
|
|
|
item.SetFetchingData();
|
2024-06-11 21:58:44 +00:00
|
|
|
}
|
|
|
|
|
2024-08-05 03:06:40 +00:00
|
|
|
for (int i = 0; i < FilteredItems.Count; i++){
|
2024-06-11 21:58:44 +00:00
|
|
|
FetchingData = true;
|
|
|
|
RaisePropertyChanged(nameof(FetchingData));
|
2024-08-05 03:06:40 +00:00
|
|
|
await FilteredItems[i].FetchData("");
|
|
|
|
FilteredItems[i].UpdateNewEpisodes();
|
2024-05-10 22:08:25 +00:00
|
|
|
}
|
2024-05-11 11:08:24 +00:00
|
|
|
|
2024-06-11 21:58:44 +00:00
|
|
|
FetchingData = false;
|
|
|
|
RaisePropertyChanged(nameof(FetchingData));
|
2024-07-21 09:30:20 +00:00
|
|
|
CrunchyrollManager.Instance.History.SortItems();
|
2024-05-10 22:08:25 +00:00
|
|
|
}
|
2024-05-11 11:08:24 +00:00
|
|
|
|
2024-05-10 22:08:25 +00:00
|
|
|
[RelayCommand]
|
|
|
|
public async void AddMissingToQueue(){
|
2024-08-05 03:06:40 +00:00
|
|
|
var tasks = FilteredItems
|
|
|
|
.Select(item => item.AddNewMissingToDownloads());
|
|
|
|
|
|
|
|
await Task.WhenAll(tasks);
|
|
|
|
}
|
|
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
public async Task DownloadMissingSonarr(){
|
|
|
|
await Task.WhenAll(
|
|
|
|
FilteredItems.Where(series => !string.IsNullOrEmpty(series.SonarrSeriesId))
|
|
|
|
.SelectMany(item => item.Seasons)
|
|
|
|
.SelectMany(season => season.EpisodesList)
|
|
|
|
.Where(historyEpisode => !string.IsNullOrEmpty(historyEpisode.SonarrEpisodeId) && !historyEpisode.SonarrHasFile)
|
|
|
|
.Select(historyEpisode => historyEpisode.DownloadEpisode())
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
public async Task AddMissingSonarrSeriesToHistory(){
|
|
|
|
SonarrOptionsOpen = false;
|
|
|
|
AddingMissingSonarrSeries = true;
|
|
|
|
FetchingData = true;
|
|
|
|
|
|
|
|
var crInstance = CrunchyrollManager.Instance;
|
|
|
|
|
|
|
|
if (crInstance.AllCRSeries == null){
|
|
|
|
crInstance.AllCRSeries = await crInstance.CrSeries.GetAllSeries(string.IsNullOrEmpty(crInstance.CrunOptions.HistoryLang) ? crInstance.DefaultLocale : crInstance.CrunOptions.HistoryLang);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (crInstance.AllCRSeries?.Data is{ Count: > 0 }){
|
|
|
|
var concurrentSeriesIds = new ConcurrentBag<string>();
|
|
|
|
|
|
|
|
Parallel.ForEach(SonarrClient.Instance.SonarrSeries, series => {
|
|
|
|
if (crInstance.HistoryList.All(historySeries => historySeries.SonarrSeriesId != series.Id.ToString())){
|
|
|
|
var match = crInstance.History.FindClosestMatchCrSeries(crInstance.AllCRSeries.Data, series.Title);
|
|
|
|
|
|
|
|
if (match != null){
|
|
|
|
Console.WriteLine($"[Sonarr Match] Found match with {series.Title} and CR - {match.Title}");
|
|
|
|
if (!string.IsNullOrEmpty(match.Id)){
|
|
|
|
concurrentSeriesIds.Add(match.Id);
|
|
|
|
} else{
|
|
|
|
Console.Error.WriteLine($"[Sonarr Match] Series ID empty for {series.Title}");
|
|
|
|
}
|
|
|
|
} else{
|
|
|
|
Console.Error.WriteLine($"[Sonarr Match] Could not match {series.Title}");
|
|
|
|
}
|
|
|
|
} else{
|
|
|
|
Console.Error.WriteLine($"[Sonarr Match] {series.Title} already matched");
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
var seriesIds = concurrentSeriesIds.ToList();
|
|
|
|
var totalSeries = seriesIds.Count;
|
|
|
|
|
|
|
|
for (int count = 0; count < totalSeries; count++){
|
|
|
|
ProgressText = $"{count + 1}/{totalSeries}";
|
|
|
|
|
|
|
|
// Await the CRUpdateSeries task for each seriesId
|
|
|
|
await crInstance.History.CRUpdateSeries(seriesIds[count], "");
|
|
|
|
}
|
|
|
|
|
|
|
|
// var updateTasks = seriesIds.Select(seriesId => crInstance.History.CRUpdateSeries(seriesId, ""));
|
|
|
|
// await Task.WhenAll(updateTasks);
|
|
|
|
}
|
|
|
|
|
|
|
|
ProgressText = "";
|
|
|
|
AddingMissingSonarrSeries = false;
|
|
|
|
FetchingData = false;
|
|
|
|
if (SelectedFilter != null){
|
|
|
|
OnSelectedFilterChanged(SelectedFilter);
|
2024-05-04 15:35:32 +00:00
|
|
|
}
|
|
|
|
}
|
2024-06-26 22:04:50 +00:00
|
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
public async Task OpenFolderDialogAsyncSeason(HistorySeason? season){
|
|
|
|
if (_storageProvider == null){
|
|
|
|
Console.Error.WriteLine("StorageProvider must be set before using the dialog.");
|
|
|
|
throw new InvalidOperationException("StorageProvider must be set before using the dialog.");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var result = await _storageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions{
|
|
|
|
Title = "Select Folder"
|
|
|
|
});
|
|
|
|
|
|
|
|
if (result.Count > 0){
|
|
|
|
var selectedFolder = result[0];
|
|
|
|
// Do something with the selected folder path
|
|
|
|
Console.WriteLine($"Selected folder: {selectedFolder.Path.LocalPath}");
|
|
|
|
|
|
|
|
if (season != null){
|
|
|
|
season.SeasonDownloadPath = selectedFolder.Path.LocalPath;
|
2024-07-16 23:52:46 +00:00
|
|
|
CfgManager.UpdateHistoryFile();
|
2024-06-26 22:04:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[RelayCommand]
|
|
|
|
public async Task OpenFolderDialogAsyncSeries(HistorySeries? series){
|
|
|
|
if (_storageProvider == null){
|
|
|
|
Console.Error.WriteLine("StorageProvider must be set before using the dialog.");
|
|
|
|
throw new InvalidOperationException("StorageProvider must be set before using the dialog.");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var result = await _storageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions{
|
|
|
|
Title = "Select Folder"
|
|
|
|
});
|
|
|
|
|
|
|
|
if (result.Count > 0){
|
|
|
|
var selectedFolder = result[0];
|
|
|
|
// Do something with the selected folder path
|
|
|
|
Console.WriteLine($"Selected folder: {selectedFolder.Path.LocalPath}");
|
|
|
|
|
|
|
|
if (series != null){
|
|
|
|
series.SeriesDownloadPath = selectedFolder.Path.LocalPath;
|
2024-07-16 23:52:46 +00:00
|
|
|
CfgManager.UpdateHistoryFile();
|
2024-06-26 22:04:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-08-05 03:06:40 +00:00
|
|
|
|
2024-07-23 19:14:55 +00:00
|
|
|
[RelayCommand]
|
|
|
|
public async Task DownloadSeasonAll(HistorySeason season){
|
2024-08-05 03:06:40 +00:00
|
|
|
var downloadTasks = season.EpisodesList
|
|
|
|
.Select(episode => episode.DownloadEpisode());
|
|
|
|
|
|
|
|
await Task.WhenAll(downloadTasks);
|
2024-07-23 19:14:55 +00:00
|
|
|
}
|
2024-08-05 03:06:40 +00:00
|
|
|
|
2024-07-23 19:14:55 +00:00
|
|
|
[RelayCommand]
|
|
|
|
public async Task DownloadSeasonMissing(HistorySeason season){
|
2024-08-05 03:06:40 +00:00
|
|
|
var downloadTasks = season.EpisodesList
|
|
|
|
.Where(episode => !episode.WasDownloaded)
|
|
|
|
.Select(episode => episode.DownloadEpisode());
|
|
|
|
|
|
|
|
await Task.WhenAll(downloadTasks);
|
2024-07-23 19:14:55 +00:00
|
|
|
}
|
2024-08-05 03:06:40 +00:00
|
|
|
|
2024-07-23 19:14:55 +00:00
|
|
|
[RelayCommand]
|
|
|
|
public async Task DownloadSeasonMissingSonarr(HistorySeason season){
|
2024-08-05 03:06:40 +00:00
|
|
|
var downloadTasks = season.EpisodesList
|
|
|
|
.Where(episode => !episode.SonarrHasFile)
|
|
|
|
.Select(episode => episode.DownloadEpisode());
|
|
|
|
|
|
|
|
await Task.WhenAll(downloadTasks);
|
2024-07-23 19:14:55 +00:00
|
|
|
}
|
2024-06-26 22:04:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
public void SetStorageProvider(IStorageProvider storageProvider){
|
|
|
|
_storageProvider = storageProvider ?? throw new ArgumentNullException(nameof(storageProvider));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public class HistoryPageProperties(){
|
|
|
|
public SortingType? SelectedSorting{ get; set; }
|
|
|
|
public HistoryViewType SelectedView{ get; set; }
|
2024-08-05 03:06:40 +00:00
|
|
|
public FilterType SelectedFilter{ get; set; }
|
2024-06-26 22:04:50 +00:00
|
|
|
public double? ScaleValue{ get; set; }
|
2024-07-12 13:53:44 +00:00
|
|
|
|
|
|
|
public bool Ascending{ get; set; }
|
|
|
|
}
|
|
|
|
|
|
|
|
public class SortingListElement(){
|
|
|
|
public SortingType SelectedSorting{ get; set; }
|
|
|
|
public string? SortingTitle{ get; set; }
|
2024-08-05 03:06:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public class FilterListElement(){
|
|
|
|
public FilterType SelectedType{ get; set; }
|
|
|
|
public string? FilterTitle{ get; set; }
|
2024-05-04 15:35:32 +00:00
|
|
|
}
|