Crunchy-Downloader/CRD/ViewModels/SeriesPageViewModel.cs
Elwador 95cd06a523 Add - Added path reset buttons to Temp Folder Path, Download Folder, and Background Image settings
Add - Added background image option to the Appearance settings
Add - Background Image Settings - Added new options to control opacity and blur radius
Add - Added "Couldn't sync dubs" status if the syncing failed
Add - Added functionality to combine multiple episodes from the same season into a single entry in the calendar
Add - Added video resolution display next to dubs/subs in the downloads tab
Add - Added Cloudflare check to image loading
Add - Added hardsub selection if the current is not available
Add - Added part size setting to configure the size of parts downloaded at the same time
Add - Added quality override to history series
Add - Added history marker to search results to indicate if a series is already in the user's history
Add - Added seasons tab for seasonal releases (Spring, Summer, Fall, Winter)
Add - Added potential releases and release times for the current day and the next week to the custom calendar
Chg - Changed Calendar cards background color for improved visibility
Chg - Combined Appearance settings into a single section in the settings tab
Chg - Consolidated Debug settings into one settings expander for better organization
Chg - Changed time sync to now check both the start and end of the video
Chg - Changed encoding progress to be displayed by the progress bar
Chg - Updated the functionality for hiding dubs in the custom calendar
Chg - Adjusted Dub sync to improve accuracy, resolving issues where it failed for more episodes than expected
Chg - Subtitles and dubs are now sorted according to the order selected in the MKV file
Chg - Changed logout behavior to correctly log out if login fails when starting the downloader
Chg - Changed that all downloaded files are removed if an in-progress download is removed from the queue
Chg - Changed default profile image
Chg - Updated used packages to the newest version
Chg - Separated settings to separate tabs
Fix - Fixed some series didn't get added to the history
Fix - Fixed an issue with file path length that prevented some files from being accessed properly
Fix - Fixed an issue where file names exceeded the maximum allowable length, causing errors
Fix - Fixed an issue where refreshing a series could get stuck
Fix - Fixed a crash that could happen with the syncing
Fix - Fixed an issue where the download status showed "Done" while moving files from the temp folder
Fix - Fixed an issue where cookies were not being utilized correctly
Fix - Resolved issues with displaying dates in UTC format
Fix - Fixed an issue with incorrect calendar grouping
Fix - Fixed an issue with the previous week navigation in the calendar
Fix - Fixed an issue where the calendar would not display correctly when not logged in
Fix - Fixed incorrect FFmpeg check for other OS (Linux/macOS)
Fix - Fixed an issue where image loading used a different HTTP client
2024-12-19 19:01:50 +01:00

268 lines
No EOL
9.2 KiB
C#

using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Avalonia.Platform.Storage;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CRD.Downloader;
using CRD.Downloader.Crunchyroll;
using CRD.Utils;
using CRD.Utils.Files;
using CRD.Utils.Structs;
using CRD.Utils.Structs.History;
using CRD.ViewModels.Utils;
using CRD.Views;
using CRD.Views.Utils;
using FluentAvalonia.UI.Controls;
using ReactiveUI;
namespace CRD.ViewModels;
public partial class SeriesPageViewModel : ViewModelBase{
[ObservableProperty]
public HistorySeries _selectedSeries;
[ObservableProperty]
public static bool _editMode;
[ObservableProperty]
public static bool _sonarrAvailable;
[ObservableProperty]
public static bool _sonarrConnected;
private IStorageProvider? _storageProvider;
[ObservableProperty]
private string _availableDubs;
[ObservableProperty]
private string _availableSubs;
[ObservableProperty]
private string _seriesFolderPath;
[ObservableProperty]
public bool _seriesFolderPathExists;
public SeriesPageViewModel(){
_storageProvider = ProgramManager.Instance.StorageProvider ?? throw new ArgumentNullException(nameof(ProgramManager.Instance.StorageProvider));
_selectedSeries = CrunchyrollManager.Instance.SelectedSeries;
if (_selectedSeries.ThumbnailImage == null){
_selectedSeries.LoadImage();
}
if (CrunchyrollManager.Instance.CrunOptions.SonarrProperties != null){
SonarrConnected = CrunchyrollManager.Instance.CrunOptions.SonarrProperties.SonarrEnabled;
if (!string.IsNullOrEmpty(SelectedSeries.SonarrSeriesId)){
SonarrAvailable = SelectedSeries.SonarrSeriesId.Length > 0 && SonarrConnected;
} else{
SonarrAvailable = false;
}
} else{
SonarrConnected = SonarrAvailable = false;
}
AvailableDubs = "Available Dubs: " + string.Join(", ", SelectedSeries.HistorySeriesAvailableDubLang);
AvailableSubs = "Available Subs: " + string.Join(", ", SelectedSeries.HistorySeriesAvailableSoftSubs);
UpdateSeriesFolderPath();
}
private void UpdateSeriesFolderPath(){
var season = SelectedSeries.Seasons.FirstOrDefault(season => !string.IsNullOrEmpty(season.SeasonDownloadPath));
if (!string.IsNullOrEmpty(SelectedSeries.SeriesDownloadPath) && Directory.Exists(SelectedSeries.SeriesDownloadPath)){
SeriesFolderPath = SelectedSeries.SeriesDownloadPath;
SeriesFolderPathExists = true;
}
if (season is{ SeasonDownloadPath: not null }){
try{
var seasonPath = season.SeasonDownloadPath;
var directoryInfo = new DirectoryInfo(seasonPath);
string parentFolderPath = directoryInfo.Parent?.FullName;
if (Directory.Exists(parentFolderPath)){
SeriesFolderPath = parentFolderPath;
SeriesFolderPathExists = true;
}
} catch (Exception e){
Console.Error.WriteLine($"An error occurred while opening the folder: {e.Message}");
}
} else{
var customPath = string.Empty;
if (string.IsNullOrEmpty(SelectedSeries.SeriesTitle))
return;
var seriesTitle = FileNameManager.CleanupFilename(SelectedSeries.SeriesTitle);
if (string.IsNullOrEmpty(seriesTitle))
return;
// Check Crunchyroll download directory
var downloadDirPath = CrunchyrollManager.Instance.CrunOptions.DownloadDirPath;
if (!string.IsNullOrEmpty(downloadDirPath)){
customPath = System.IO.Path.Combine(downloadDirPath, seriesTitle);
} else{
// Fallback to configured VIDEOS_DIR path
customPath = System.IO.Path.Combine(CfgManager.PathVIDEOS_DIR, seriesTitle);
}
// Check if custom path exists
if (Directory.Exists(customPath)){
SeriesFolderPath = customPath;
SeriesFolderPathExists = true;
}
}
}
[RelayCommand]
public async Task OpenFolderDialogAsync(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();
} else{
SelectedSeries.SeriesDownloadPath = selectedFolder.Path.LocalPath;
CfgManager.UpdateHistoryFile();
}
}
UpdateSeriesFolderPath();
}
[RelayCommand]
public async Task MatchSonarrSeries_Button(){
var dialog = new ContentDialog(){
Title = "Sonarr Matching",
PrimaryButtonText = "Save",
CloseButtonText = "Close",
FullSizeDesired = true
};
var viewModel = new ContentDialogSonarrMatchViewModel(dialog, SelectedSeries.SonarrSeriesId, SelectedSeries.SeriesTitle);
dialog.Content = new ContentDialogSonarrMatchView(){
DataContext = viewModel
};
var dialogResult = await dialog.ShowAsync();
if (dialogResult == ContentDialogResult.Primary){
SelectedSeries.SonarrSeriesId = viewModel.CurrentSonarrSeries.Id.ToString();
SelectedSeries.SonarrTvDbId = viewModel.CurrentSonarrSeries.TvdbId.ToString();
SelectedSeries.SonarrSlugTitle = viewModel.CurrentSonarrSeries.TitleSlug;
if (CrunchyrollManager.Instance.CrunOptions.SonarrProperties != null){
SonarrConnected = CrunchyrollManager.Instance.CrunOptions.SonarrProperties.SonarrEnabled;
if (!string.IsNullOrEmpty(SelectedSeries.SonarrSeriesId)){
SonarrAvailable = SelectedSeries.SonarrSeriesId.Length > 0 && SonarrConnected;
} else{
SonarrAvailable = false;
}
} else{
SonarrConnected = SonarrAvailable = false;
}
UpdateData("");
}
}
[RelayCommand]
public async Task DownloadSeasonAll(HistorySeason season){
var downloadTasks = season.EpisodesList
.Select(episode => episode.DownloadEpisode());
await Task.WhenAll(downloadTasks);
}
[RelayCommand]
public async Task DownloadSeasonMissing(HistorySeason season){
var downloadTasks = season.EpisodesList
.Where(episode => !episode.WasDownloaded)
.Select(episode => episode.DownloadEpisode()).ToList();
if (downloadTasks.Count == 0){
MessageBus.Current.SendMessage(new ToastMessage($"There are no missing episodes", ToastType.Error, 3));
} else{
await Task.WhenAll(downloadTasks);
}
}
[RelayCommand]
public async Task DownloadSeasonMissingSonarr(HistorySeason season){
var downloadTasks = season.EpisodesList
.Where(episode => !episode.SonarrHasFile)
.Select(episode => episode.DownloadEpisode());
await Task.WhenAll(downloadTasks);
}
[RelayCommand]
public async Task UpdateData(string? season){
await SelectedSeries.FetchData(season);
SelectedSeries.Seasons.Refresh();
AvailableDubs = "Available Dubs: " + string.Join(", ", SelectedSeries.HistorySeriesAvailableDubLang);
AvailableSubs = "Available Subs: " + string.Join(", ", SelectedSeries.HistorySeriesAvailableSoftSubs);
// MessageBus.Current.SendMessage(new NavigationMessage(typeof(SeriesPageViewModel), false, true));
}
[RelayCommand]
public void RemoveSeason(string? season){
HistorySeason? objectToRemove = SelectedSeries.Seasons.FirstOrDefault(se => se.SeasonId == season) ?? null;
if (objectToRemove != null){
SelectedSeries.Seasons.Remove(objectToRemove);
CfgManager.UpdateHistoryFile();
}
MessageBus.Current.SendMessage(new NavigationMessage(typeof(SeriesPageViewModel), false, true));
}
[RelayCommand]
public void NavBack(){
SelectedSeries.UpdateNewEpisodes();
MessageBus.Current.SendMessage(new NavigationMessage(null, true, false));
}
[RelayCommand]
public void OpenFolderPath(){
try{
Process.Start(new ProcessStartInfo{
FileName = SeriesFolderPath,
UseShellExecute = true,
Verb = "open"
});
} catch (Exception ex){
Console.Error.WriteLine($"An error occurred while opening the folder: {ex.Message}");
}
}
}