361 lines
12 KiB
C#
361 lines
12 KiB
C#
using System;
|
|
using System.Collections.ObjectModel;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Runtime.Serialization;
|
|
using System.Threading.Tasks;
|
|
using Avalonia;
|
|
using Avalonia.Controls;
|
|
using Avalonia.Platform.Storage;
|
|
using Avalonia.Threading;
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CommunityToolkit.Mvvm.Input;
|
|
using CRD.Downloader;
|
|
using CRD.Downloader.Crunchyroll;
|
|
using CRD.Utils;
|
|
using CRD.Utils.Structs;
|
|
using CRD.Utils.Structs.History;
|
|
using CRD.Views;
|
|
using DynamicData;
|
|
using ReactiveUI;
|
|
|
|
namespace CRD.ViewModels;
|
|
|
|
public partial class HistoryPageViewModel : ViewModelBase{
|
|
public ObservableCollection<HistorySeries> Items{ get; }
|
|
|
|
[ObservableProperty]
|
|
private static bool _fetchingData;
|
|
|
|
[ObservableProperty]
|
|
public HistorySeries _selectedSeries;
|
|
|
|
[ObservableProperty]
|
|
public static bool _editMode;
|
|
|
|
[ObservableProperty]
|
|
public double _scaleValue;
|
|
|
|
[ObservableProperty]
|
|
public ComboBoxItem _selectedView;
|
|
|
|
public ObservableCollection<ComboBoxItem> ViewsList{ get; } =[];
|
|
|
|
[ObservableProperty]
|
|
public SortingListElement _selectedSorting;
|
|
|
|
public ObservableCollection<SortingListElement> SortingList{ get; } =[];
|
|
|
|
[ObservableProperty]
|
|
public double _posterWidth;
|
|
|
|
[ObservableProperty]
|
|
public double _posterHeight;
|
|
|
|
[ObservableProperty]
|
|
public double _posterImageWidth;
|
|
|
|
[ObservableProperty]
|
|
public double _posterImageHeight;
|
|
|
|
[ObservableProperty]
|
|
public double _posterTextSize;
|
|
|
|
[ObservableProperty]
|
|
public Thickness _cornerMargin;
|
|
|
|
private HistoryViewType currentViewType = HistoryViewType.Posters;
|
|
|
|
[ObservableProperty]
|
|
public bool _isPosterViewSelected = false;
|
|
|
|
[ObservableProperty]
|
|
public bool _isTableViewSelected = false;
|
|
|
|
[ObservableProperty]
|
|
public static bool _viewSelectionOpen;
|
|
|
|
[ObservableProperty]
|
|
public static bool _sortingSelectionOpen;
|
|
|
|
private IStorageProvider _storageProvider;
|
|
|
|
private SortingType currentSortingType = SortingType.NextAirDate;
|
|
|
|
[ObservableProperty]
|
|
public static bool _sortDir = false;
|
|
|
|
public HistoryPageViewModel(){
|
|
Items = CrunchyrollManager.Instance.HistoryList;
|
|
|
|
HistoryPageProperties? properties = CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties;
|
|
|
|
currentViewType = properties?.SelectedView ?? HistoryViewType.Posters;
|
|
currentSortingType = properties?.SelectedSorting ?? SortingType.SeriesTitle;
|
|
ScaleValue = properties?.ScaleValue ?? 0.73;
|
|
SortDir = properties?.Ascending ?? false;
|
|
|
|
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))){
|
|
var combobox = new SortingListElement(){ SortingTitle = sortingType.GetEnumMemberValue(), SelectedSorting = sortingType };
|
|
SortingList.Add(combobox);
|
|
if (sortingType == currentSortingType){
|
|
SelectedSorting = combobox;
|
|
}
|
|
}
|
|
|
|
IsPosterViewSelected = currentViewType == HistoryViewType.Posters;
|
|
IsTableViewSelected = currentViewType == HistoryViewType.Table;
|
|
|
|
|
|
foreach (var historySeries in Items){
|
|
if (historySeries.ThumbnailImage == null){
|
|
historySeries.LoadImage();
|
|
}
|
|
|
|
historySeries.UpdateNewEpisodes();
|
|
}
|
|
|
|
CrunchyrollManager.Instance.History.SortItems();
|
|
}
|
|
|
|
|
|
private void UpdateSettings(){
|
|
if (CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties != null){
|
|
CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.ScaleValue = ScaleValue;
|
|
CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.SelectedView = currentViewType;
|
|
CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.SelectedSorting = currentSortingType;
|
|
} else{
|
|
CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties = new HistoryPageProperties(){ ScaleValue = ScaleValue, SelectedView = currentViewType, SelectedSorting = currentSortingType };
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
|
|
partial void OnSelectedSortingChanged(SortingListElement? oldValue, SortingListElement? newValue){
|
|
if (newValue == null){
|
|
if (CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties != null){
|
|
CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.Ascending = !CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.Ascending;
|
|
SortDir = CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.Ascending;
|
|
}
|
|
|
|
Dispatcher.UIThread.InvokeAsync(() => {
|
|
SelectedSorting = oldValue ?? SortingList.First();
|
|
RaisePropertyChanged(nameof(SelectedSorting));
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (newValue.SelectedSorting != null){
|
|
currentSortingType = newValue.SelectedSorting;
|
|
if (CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties != null) CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.SelectedSorting = currentSortingType;
|
|
CrunchyrollManager.Instance.History.SortItems();
|
|
} else{
|
|
Console.Error.WriteLine("Invalid viewtype selected");
|
|
}
|
|
|
|
SortingSelectionOpen = false;
|
|
UpdateSettings();
|
|
}
|
|
|
|
private bool TryParseEnum<T>(string value, out T result) where T : struct, Enum{
|
|
foreach (var field in typeof(T).GetFields()){
|
|
var attribute = field.GetCustomAttribute<EnumMemberAttribute>();
|
|
if (attribute != null && attribute.Value == value){
|
|
result = (T)field.GetValue(null);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
result = default;
|
|
return false;
|
|
}
|
|
|
|
|
|
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();
|
|
}
|
|
|
|
|
|
partial void OnSelectedSeriesChanged(HistorySeries value){
|
|
CrunchyrollManager.Instance.SelectedSeries = value;
|
|
|
|
NavToSeries();
|
|
|
|
if (!string.IsNullOrEmpty(value.SonarrSeriesId) && CrunchyrollManager.Instance.CrunOptions.SonarrProperties is{ SonarrEnabled: true }){
|
|
CrunchyrollManager.Instance.History.MatchHistoryEpisodesWithSonarr(true, SelectedSeries);
|
|
}
|
|
|
|
|
|
_selectedSeries = null;
|
|
}
|
|
|
|
[RelayCommand]
|
|
public void RemoveSeries(string? seriesId){
|
|
HistorySeries? objectToRemove = CrunchyrollManager.Instance.HistoryList.ToList().Find(se => se.SeriesId == seriesId) ?? null;
|
|
if (objectToRemove != null){
|
|
CrunchyrollManager.Instance.HistoryList.Remove(objectToRemove);
|
|
Items.Remove(objectToRemove);
|
|
CfgManager.UpdateHistoryFile();
|
|
}
|
|
}
|
|
|
|
|
|
[RelayCommand]
|
|
public void NavToSeries(){
|
|
if (FetchingData){
|
|
return;
|
|
}
|
|
|
|
MessageBus.Current.SendMessage(new NavigationMessage(typeof(SeriesPageViewModel), false, false));
|
|
}
|
|
|
|
[RelayCommand]
|
|
public async void RefreshAll(){
|
|
FetchingData = true;
|
|
RaisePropertyChanged(nameof(FetchingData));
|
|
for (int i = 0; i < Items.Count; i++){
|
|
Items[i].SetFetchingData();
|
|
}
|
|
|
|
for (int i = 0; i < Items.Count; i++){
|
|
FetchingData = true;
|
|
RaisePropertyChanged(nameof(FetchingData));
|
|
await Items[i].FetchData("");
|
|
Items[i].UpdateNewEpisodes();
|
|
}
|
|
|
|
FetchingData = false;
|
|
RaisePropertyChanged(nameof(FetchingData));
|
|
CrunchyrollManager.Instance.History.SortItems();
|
|
}
|
|
|
|
[RelayCommand]
|
|
public async void AddMissingToQueue(){
|
|
for (int i = 0; i < Items.Count; i++){
|
|
await Items[i].AddNewMissingToDownloads();
|
|
}
|
|
}
|
|
|
|
[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;
|
|
CfgManager.UpdateHistoryFile();
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
[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;
|
|
CfgManager.UpdateHistoryFile();
|
|
}
|
|
}
|
|
}
|
|
|
|
[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){
|
|
_storageProvider = storageProvider ?? throw new ArgumentNullException(nameof(storageProvider));
|
|
}
|
|
}
|
|
|
|
public class HistoryPageProperties(){
|
|
public SortingType? SelectedSorting{ get; set; }
|
|
public HistoryViewType SelectedView{ get; set; }
|
|
public double? ScaleValue{ get; set; }
|
|
|
|
public bool Ascending{ get; set; }
|
|
}
|
|
|
|
public class SortingListElement(){
|
|
public SortingType SelectedSorting{ get; set; }
|
|
public string? SortingTitle{ get; set; }
|
|
} |