Add - Downloader remembers the Window Size and Position https://github.com/Crunchy-DL/Crunchy-Downloader/discussions/78

Chg - Adjusted the subscription check if the end date has passed but crunchyroll still thinks it's active https://github.com/Crunchy-DL/Crunchy-Downloader/issues/80
This commit is contained in:
Elwador 2024-08-16 14:21:23 +02:00
parent 6aa10cb2c2
commit 9c6ad2d7e8
9 changed files with 229 additions and 224 deletions

View File

@ -44,7 +44,6 @@ public class CrAuth{
PreferredContentAudioLanguage = "ja-JP",
PreferredContentSubtitleLanguage = "de-DE"
};
}
private void JsonTokenToFileAndVariable(string content){
@ -52,7 +51,7 @@ public class CrAuth{
if (crunInstance.Token != null && crunInstance.Token.expires_in != null){
crunInstance.Token.expires = DateTime.Now.AddMilliseconds((double)crunInstance.Token.expires_in);
crunInstance.Token.expires = DateTime.Now.AddSeconds((double)crunInstance.Token.expires_in);
CfgManager.WriteTokenToYamlFile(crunInstance.Token, CfgManager.PathCrToken);
}
@ -82,7 +81,8 @@ public class CrAuth{
if (response.ResponseContent.Contains("invalid_credentials")){
MessageBus.Current.SendMessage(new ToastMessage($"Failed to login - because of invalid login credentials", ToastType.Error, 10));
} else{
MessageBus.Current.SendMessage(new ToastMessage($"Failed to login - {response.ResponseContent.Substring(0,response.ResponseContent.Length < 200 ? response.ResponseContent.Length : 200)}", ToastType.Error, 10));
MessageBus.Current.SendMessage(new ToastMessage($"Failed to login - {response.ResponseContent.Substring(0, response.ResponseContent.Length < 200 ? response.ResponseContent.Length : 200)}",
ToastType.Error, 10));
}
}
@ -119,20 +119,27 @@ public class CrAuth{
if (subsc is{ SubscriptionProducts:{ Count: 0 }, ThirdPartySubscriptionProducts.Count: > 0 }){
var thirdPartySub = subsc.ThirdPartySubscriptionProducts.First();
var expiration = thirdPartySub.InGrace ? thirdPartySub.InGraceExpirationDate : thirdPartySub.ExpirationDate;
var remaining = expiration - DateTime.UtcNow;
crunInstance.Profile.HasPremium = remaining > TimeSpan.Zero;
crunInstance.Profile.Subscription.IsActive = remaining > TimeSpan.Zero;
crunInstance.Profile.Subscription.NextRenewalDate = expiration;
var remaining = expiration - DateTime.Now;
crunInstance.Profile.HasPremium = true;
if (crunInstance.Profile.Subscription != null){
crunInstance.Profile.Subscription.IsActive = remaining > TimeSpan.Zero;
crunInstance.Profile.Subscription.NextRenewalDate = expiration;
}
} else if (subsc is{ SubscriptionProducts:{ Count: 0 }, NonrecurringSubscriptionProducts.Count: > 0 }){
var nonRecurringSub = subsc.NonrecurringSubscriptionProducts.First();
var remaining = nonRecurringSub.EndDate - DateTime.UtcNow;
crunInstance.Profile.HasPremium = remaining > TimeSpan.Zero;
crunInstance.Profile.Subscription.IsActive = remaining > TimeSpan.Zero;
crunInstance.Profile.Subscription.NextRenewalDate = nonRecurringSub.EndDate;
var remaining = nonRecurringSub.EndDate - DateTime.Now;
crunInstance.Profile.HasPremium = true;
if (crunInstance.Profile.Subscription != null){
crunInstance.Profile.Subscription.IsActive = remaining > TimeSpan.Zero;
crunInstance.Profile.Subscription.NextRenewalDate = nonRecurringSub.EndDate;
}
} else if (subsc is{ SubscriptionProducts:{ Count: 0 }, FunimationSubscriptions.Count: > 0 }){
crunInstance.Profile.HasPremium = true;
} else if (subsc is{ SubscriptionProducts.Count: > 0 }){
crunInstance.Profile.HasPremium = true;
} else{
crunInstance.Profile.HasPremium = subsc.IsActive;
crunInstance.Profile.HasPremium = false;
Console.Error.WriteLine($"No subscription available:\n {JsonConvert.SerializeObject(subsc, Formatting.Indented)} ");
}
} else{
crunInstance.Profile.HasPremium = false;
@ -175,7 +182,6 @@ public class CrAuth{
await GetProfile();
}
}
public async Task RefreshToken(bool needsToken){
@ -213,7 +219,5 @@ public class CrAuth{
} else{
Console.Error.WriteLine("Refresh Token Auth Failed");
}
}
}

View File

@ -59,7 +59,7 @@ public class CrEpisode(){
CrunchyRollEpisodeData episode = new CrunchyRollEpisodeData();
if (crunInstance.CrunOptions.History && updateHistory){
await crunInstance.History.UpdateWithEpisode(dlEpisode);
await crunInstance.History.UpdateWithSeasonData(new List<CrunchyEpisode>(){dlEpisode});
var historySeries = crunInstance.HistoryList.FirstOrDefault(series => series.SeriesId == dlEpisode.SeriesId);
if (historySeries != null){
CrunchyrollManager.Instance.History.MatchHistorySeriesWithSonarr(false);

View File

@ -16,26 +16,6 @@ namespace CRD.Downloader.Crunchyroll;
public class CrSeries(){
private readonly CrunchyrollManager crunInstance = CrunchyrollManager.Instance;
public async Task<List<CrunchyEpMeta>> DownloadFromSeriesId(string id, CrunchyMultiDownload data){
var series = await ListSeriesId(id, "", data);
if (series != null){
var selected = ItemSelectMultiDub(series.Value.Data, data.DubLang, data.But, data.AllEpisodes, data.E);
foreach (var crunchyEpMeta in selected.Values){
if (crunchyEpMeta.Data == null) continue;
var languages = crunchyEpMeta.Data.Select((a) =>
$" {a.Lang?.Name ?? "Unknown Language"}");
Console.WriteLine($"[S{crunchyEpMeta.Season}E{crunchyEpMeta.EpisodeNumber} - {crunchyEpMeta.EpisodeTitle} [{string.Join(", ", languages)}]");
}
return selected.Values.ToList();
}
return new List<CrunchyEpMeta>();
}
public Dictionary<string, CrunchyEpMeta> ItemSelectMultiDub(Dictionary<string, EpisodeAndLanguage> eps, List<string> dubLang, bool? but, bool? all, List<string>? e){
var ret = new Dictionary<string, CrunchyEpMeta>();
@ -143,25 +123,31 @@ public class CrSeries(){
CrSeriesSearch? parsedSeries = await ParseSeriesById(id, crLocale); // one piece - GRMG8ZQZR
if (parsedSeries == null){
if (parsedSeries == null || parsedSeries.Data == null){
Console.Error.WriteLine("Parse Data Invalid");
return null;
}
var result = ParseSeriesResult(parsedSeries);
// var result = ParseSeriesResult(parsedSeries);
Dictionary<string, EpisodeAndLanguage> episodes = new Dictionary<string, EpisodeAndLanguage>();
if (crunInstance.CrunOptions.History){
crunInstance.History.CRUpdateSeries(id,"");
}
foreach (int season in result.Keys){
foreach (var key in result[season].Keys){
var s = result[season][key];
var cachedSeasonID = "";
var seasonData = new CrunchyEpisodeList();
foreach (var s in parsedSeries.Data){
if (data?.S != null && s.Id != data.Value.S) continue;
int fallbackIndex = 0;
var seasonData = await GetSeasonDataById(s.Id, "");
if (cachedSeasonID != s.Id){
seasonData = await GetSeasonDataById(s.Id, "");
cachedSeasonID = s.Id;
}
if (seasonData.Data != null){
if (crunInstance.CrunOptions.History){
crunInstance.History.UpdateWithSeasonData(seasonData, false);
}
foreach (var episode in seasonData.Data){
// Prepare the episode array
@ -204,7 +190,6 @@ public class CrSeries(){
}
}
}
}
}
if (crunInstance.CrunOptions.History){

View File

@ -22,45 +22,40 @@ public class History(){
public async Task CRUpdateSeries(string seriesId, string? seasonId){
await crunInstance.CrAuth.RefreshToken(true);
CrSeriesSearch? parsedSeries = await crunInstance.CrSeries.ParseSeriesById(seriesId, "ja-JP", true);
CrSeriesSearch? parsedSeries = await crunInstance.CrSeries.ParseSeriesById(seriesId, "en-US", true);
if (parsedSeries == null){
Console.Error.WriteLine("Parse Data Invalid");
return;
}
var result = crunInstance.CrSeries.ParseSeriesResult(parsedSeries);
Dictionary<string, EpisodeAndLanguage> episodes = new Dictionary<string, EpisodeAndLanguage>();
foreach (int season in result.Keys){
foreach (var key in result[season].Keys){
var s = result[season][key];
if (parsedSeries.Data != null){
foreach (var s in parsedSeries.Data){
if (!string.IsNullOrEmpty(seasonId) && s.Id != seasonId) continue;
var sId = s.Id;
if (s.Versions is{ Count: > 0 }){
foreach (var sVersion in s.Versions){
if (sVersion.Original == true){
if (sVersion.Guid != null){
sId = sVersion.Guid;
}
break;
foreach (var sVersion in s.Versions.Where(sVersion => sVersion.Original == true)){
if (sVersion.Guid != null){
sId = sVersion.Guid;
}
break;
}
}
var seasonData = await crunInstance.CrSeries.GetSeasonDataById(sId, string.IsNullOrEmpty(crunInstance.CrunOptions.HistoryLang) ? crunInstance.DefaultLocale : crunInstance.CrunOptions.HistoryLang, true);
await UpdateWithSeasonData(seasonData);
if (seasonData.Data != null) await UpdateWithSeasonData(seasonData.Data);
}
}
var historySeries = crunInstance.HistoryList.FirstOrDefault(series => series.SeriesId == seriesId);
if (historySeries != null){
MatchHistorySeriesWithSonarr(false);
await MatchHistoryEpisodesWithSonarr(false, historySeries);
CfgManager.UpdateHistoryFile();
var historySeries = crunInstance.HistoryList.FirstOrDefault(series => series.SeriesId == seriesId);
if (historySeries != null){
MatchHistorySeriesWithSonarr(false);
await MatchHistoryEpisodesWithSonarr(false, historySeries);
CfgManager.UpdateHistoryFile();
}
}
}
@ -212,116 +207,43 @@ public class History(){
}
public async Task UpdateWithEpisode(CrunchyEpisode episodeParam){
var episode = episodeParam;
if (episode.Versions != null){
var version = episode.Versions.Find(a => a.Original);
if (version.AudioLocale != episode.AudioLocale){
var crEpisode = await crunInstance.CrEpisode.ParseEpisodeById(version.Guid, "");
if (crEpisode != null){
episode = crEpisode.Value;
} else{
MessageBus.Current.SendMessage(new ToastMessage($"Couldn't update download History", ToastType.Warning, 1));
return;
}
}
}
var seriesId = episode.SeriesId;
var historySeries = crunInstance.HistoryList.FirstOrDefault(series => series.SeriesId == seriesId);
if (historySeries != null){
historySeries.HistorySeriesAddDate ??= DateTime.Now;
var historySeason = historySeries.Seasons.FirstOrDefault(s => s.SeasonId == episode.SeasonId);
await RefreshSeriesData(seriesId, historySeries);
if (historySeason != null){
historySeason.SeasonTitle = episode.SeasonTitle;
historySeason.SeasonNum = Helpers.ExtractNumberAfterS(episode.Identifier) ?? episode.SeasonNumber + "";
historySeason.SpecialSeason = CheckStringForSpecial(episode.Identifier);
if (historySeason.EpisodesList.All(e => e.EpisodeId != episode.Id)){
var newHistoryEpisode = new HistoryEpisode{
EpisodeTitle = episode.Identifier.Contains("|M|") ? episode.SeasonTitle : episode.Title,
EpisodeDescription = episode.Description,
EpisodeId = episode.Id,
Episode = episode.Episode,
EpisodeSeasonNum = Helpers.ExtractNumberAfterS(episode.Identifier) ?? episode.SeasonNumber + "",
SpecialEpisode = !int.TryParse(episode.Episode, out _),
};
historySeason.EpisodesList.Add(newHistoryEpisode);
historySeason.EpisodesList.Sort(new NumericStringPropertyComparer());
}
} else{
var newSeason = NewHistorySeason(episode);
historySeries.Seasons.Add(newSeason);
newSeason.Init();
}
historySeries.UpdateNewEpisodes();
} else{
historySeries = new HistorySeries{
SeriesTitle = episode.SeriesTitle,
SeriesId = episode.SeriesId,
Seasons =[],
HistorySeriesAddDate = DateTime.Now,
};
crunInstance.HistoryList.Add(historySeries);
var newSeason = NewHistorySeason(episode);
await RefreshSeriesData(seriesId, historySeries);
historySeries.Seasons.Add(newSeason);
historySeries.UpdateNewEpisodes();
historySeries.Init();
newSeason.Init();
}
SortItems();
SortSeasons(historySeries);
}
public async Task UpdateWithSeasonData(CrunchyEpisodeList seasonData, bool skippVersionCheck = true){
if (seasonData.Data != null){
public async Task UpdateWithSeasonData(List<CrunchyEpisode>? episodeList, bool skippVersionCheck = true){
if (episodeList != null){
if (!skippVersionCheck){
if (seasonData.Data.First().Versions != null){
var version = seasonData.Data.First().Versions.Find(a => a.Original);
if (version.AudioLocale != seasonData.Data.First().AudioLocale){
CRUpdateSeries(seasonData.Data.First().SeriesId, version.SeasonGuid);
var episodeVersions = episodeList.First().Versions;
if (episodeVersions != null){
var version = episodeVersions.Find(a => a.Original);
if (version.AudioLocale != episodeList.First().AudioLocale){
await CRUpdateSeries(episodeList.First().SeriesId, version.SeasonGuid);
return;
}
} else{
CRUpdateSeries(seasonData.Data.First().SeriesId, "");
await CRUpdateSeries(episodeList.First().SeriesId, "");
return;
}
}
var firstEpisode = seasonData.Data.First();
var firstEpisode = episodeList.First();
var seriesId = firstEpisode.SeriesId;
var historySeries = crunInstance.HistoryList.FirstOrDefault(series => series.SeriesId == seriesId);
if (historySeries != null){
historySeries.HistorySeriesAddDate ??= DateTime.Now;
var historySeason = historySeries.Seasons.FirstOrDefault(s => s.SeasonId == firstEpisode.SeasonId);
await RefreshSeriesData(seriesId, historySeries);
var historySeason = historySeries.Seasons.FirstOrDefault(s => s.SeasonId == firstEpisode.SeasonId);
if (historySeason != null){
historySeason.SeasonTitle = firstEpisode.SeasonTitle;
historySeason.SeasonNum = Helpers.ExtractNumberAfterS(firstEpisode.Identifier) ?? firstEpisode.SeasonNumber + "";
historySeason.SpecialSeason = CheckStringForSpecial(firstEpisode.Identifier);
foreach (var crunchyEpisode in seasonData.Data){
foreach (var crunchyEpisode in episodeList){
var historyEpisode = historySeason.EpisodesList.Find(e => e.EpisodeId == crunchyEpisode.Id);
if (historyEpisode == null){
var newHistoryEpisode = new HistoryEpisode{
EpisodeTitle = crunchyEpisode.Identifier.Contains("|M|") ? crunchyEpisode.SeasonTitle : crunchyEpisode.Title,
EpisodeTitle = GetEpisodeTitle(crunchyEpisode),
EpisodeDescription = crunchyEpisode.Description,
EpisodeId = crunchyEpisode.Id,
Episode = crunchyEpisode.Episode,
@ -332,7 +254,7 @@ public class History(){
historySeason.EpisodesList.Add(newHistoryEpisode);
} else{
//Update existing episode
historyEpisode.EpisodeTitle = crunchyEpisode.Identifier.Contains("|M|") ? crunchyEpisode.SeasonTitle : crunchyEpisode.Title;
historyEpisode.EpisodeTitle = GetEpisodeTitle(crunchyEpisode);
historyEpisode.SpecialEpisode = !int.TryParse(crunchyEpisode.Episode, out _);
historyEpisode.EpisodeDescription = crunchyEpisode.Description;
historyEpisode.EpisodeId = crunchyEpisode.Id;
@ -343,7 +265,7 @@ public class History(){
historySeason.EpisodesList.Sort(new NumericStringPropertyComparer());
} else{
var newSeason = NewHistorySeason(seasonData, firstEpisode);
var newSeason = NewHistorySeason(episodeList, firstEpisode);
newSeason.EpisodesList.Sort(new NumericStringPropertyComparer());
@ -361,7 +283,7 @@ public class History(){
};
crunInstance.HistoryList.Add(historySeries);
var newSeason = NewHistorySeason(seasonData, firstEpisode);
var newSeason = NewHistorySeason(episodeList, firstEpisode);
newSeason.EpisodesList.Sort(new NumericStringPropertyComparer());
@ -381,6 +303,34 @@ public class History(){
private CrSeriesBase? cachedSeries;
private string GetEpisodeTitle(CrunchyEpisode crunchyEpisode){
if (crunchyEpisode.Identifier.Contains("|M|")){
if (string.IsNullOrEmpty(crunchyEpisode.Title)){
if (crunchyEpisode.SeasonTitle.StartsWith(crunchyEpisode.SeriesTitle)){
var splitTitle = crunchyEpisode.SeasonTitle.Split(new[]{ crunchyEpisode.SeriesTitle }, StringSplitOptions.None);
var titlePart = splitTitle.Length > 1 ? splitTitle[1] : splitTitle[0];
var cleanedTitle = Regex.Replace(titlePart, @"^[^a-zA-Z]+", "");
return cleanedTitle;
}
return crunchyEpisode.SeasonTitle;
}
if (crunchyEpisode.Title.StartsWith(crunchyEpisode.SeriesTitle)){
var splitTitle = crunchyEpisode.Title.Split(new[]{ crunchyEpisode.SeriesTitle }, StringSplitOptions.None);
var titlePart = splitTitle.Length > 1 ? splitTitle[1] : splitTitle[0];
var cleanedTitle = Regex.Replace(titlePart, @"^[^a-zA-Z]+", "");
return cleanedTitle;
}
return crunchyEpisode.Title;
}
return crunchyEpisode.Title;
}
private async Task RefreshSeriesData(string seriesId, HistorySeries historySeries){
if (cachedSeries == null || (cachedSeries.Data != null && cachedSeries.Data.First().Id != seriesId)){
cachedSeries = await crunInstance.CrSeries.SeriesById(seriesId, string.IsNullOrEmpty(crunInstance.CrunOptions.HistoryLang) ? crunInstance.DefaultLocale : crunInstance.CrunOptions.HistoryLang, true);
@ -418,7 +368,7 @@ public class History(){
public void SortItems(){
var currentSortingType = CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties?.SelectedSorting ?? SortingType.SeriesTitle;
var sortingDir = CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties != null && CrunchyrollManager.Instance.CrunOptions.HistoryPageProperties.Ascending;
DateTime today = DateTime.UtcNow.Date;
DateTime today = DateTime.Now.Date;
switch (currentSortingType){
case SortingType.SeriesTitle:
var sortedList = sortingDir
@ -479,7 +429,7 @@ public class History(){
}
}
public static DateTime? ParseDate(string dateStr, DateTime today){
public DateTime? ParseDate(string dateStr, DateTime today){
if (dateStr == "Today"){
return today;
}
@ -502,7 +452,7 @@ public class History(){
return "";
}
private static bool CheckStringForSpecial(string identifier){
private bool CheckStringForSpecial(string identifier){
if (string.IsNullOrEmpty(identifier)){
return false;
}
@ -514,7 +464,7 @@ public class History(){
return Regex.IsMatch(identifier, pattern);
}
private static HistorySeason NewHistorySeason(CrunchyEpisodeList seasonData, CrunchyEpisode firstEpisode){
private HistorySeason NewHistorySeason(List<CrunchyEpisode> seasonData, CrunchyEpisode firstEpisode){
var newSeason = new HistorySeason{
SeasonTitle = firstEpisode.SeasonTitle,
SeasonId = firstEpisode.SeasonId,
@ -523,9 +473,9 @@ public class History(){
SpecialSeason = CheckStringForSpecial(firstEpisode.Identifier)
};
foreach (var crunchyEpisode in seasonData.Data!){
foreach (var crunchyEpisode in seasonData){
var newHistoryEpisode = new HistoryEpisode{
EpisodeTitle = crunchyEpisode.Identifier.Contains("|M|") ? crunchyEpisode.SeasonTitle : crunchyEpisode.Title,
EpisodeTitle = GetEpisodeTitle(crunchyEpisode),
EpisodeDescription = crunchyEpisode.Description,
EpisodeId = crunchyEpisode.Id,
Episode = crunchyEpisode.Episode,
@ -538,31 +488,8 @@ public class History(){
return newSeason;
}
private static HistorySeason NewHistorySeason(CrunchyEpisode episode){
var newSeason = new HistorySeason{
SeasonTitle = episode.SeasonTitle,
SeasonId = episode.SeasonId,
SeasonNum = Helpers.ExtractNumberAfterS(episode.Identifier) ?? episode.SeasonNumber + "",
EpisodesList =[],
};
var newHistoryEpisode = new HistoryEpisode{
EpisodeTitle = episode.Identifier.Contains("|M|") ? episode.SeasonTitle : episode.Title,
EpisodeDescription = episode.Description,
EpisodeId = episode.Id,
Episode = episode.Episode,
EpisodeSeasonNum = Helpers.ExtractNumberAfterS(episode.Identifier) ?? episode.SeasonNumber + "",
SpecialEpisode = !int.TryParse(episode.Episode, out _),
};
newSeason.EpisodesList.Add(newHistoryEpisode);
return newSeason;
}
public async void MatchHistorySeriesWithSonarr(bool updateAll){
public void MatchHistorySeriesWithSonarr(bool updateAll){
if (crunInstance.CrunOptions.SonarrProperties is{ SonarrEnabled: false }){
return;
}
@ -604,7 +531,7 @@ public class History(){
// Create a copy of the episodes list for each thread
var episodesCopy = new List<SonarrEpisode>(episodes);
var episode = FindClosestMatchEpisodes(episodesCopy, historyEpisode.EpisodeTitle);
var episode = FindClosestMatchEpisodes(episodesCopy, historyEpisode.EpisodeTitle ?? string.Empty);
if (episode != null){
historyEpisode.SonarrEpisodeId = episode.Id + "";
historyEpisode.SonarrEpisodeNumber = episode.EpisodeNumber + "";

View File

@ -22,6 +22,7 @@ public class CfgManager{
public static readonly string PathCrToken = WorkingDirectory + "/config/cr_token.yml";
public static readonly string PathCrDownloadOptions = WorkingDirectory + "/config/settings.yml";
public static readonly string PathCrHistory = WorkingDirectory + "/config/history.json";
public static readonly string PathWindowSettings= WorkingDirectory + "/config/windowSettings.json";
public static readonly string PathFFMPEG = WorkingDirectory + "/lib/ffmpeg.exe";
public static readonly string PathMKVMERGE = WorkingDirectory + "/lib/mkvmerge.exe";

View File

@ -322,7 +322,7 @@ public class HistorySeries : INotifyPropertyChanged{
await CrunchyrollManager.Instance.History.CRUpdateSeries(SeriesId, seasonId);
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SeriesTitle)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SeriesDescription)));
CrunchyrollManager.Instance.History.MatchHistoryEpisodesWithSonarr(false, this);
// CrunchyrollManager.Instance.History.MatchHistoryEpisodesWithSonarr(false, this);
UpdateNewEpisodes();
FetchingData = false;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(FetchingData)));

View File

@ -1,4 +1,6 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using CRD.Views;
using Newtonsoft.Json;
namespace CRD.Utils.Structs;
@ -97,4 +99,30 @@ public class FrameData{
public class StringItem{
public string stringValue{ get; set; }
}
public class WindowSettings{
public double Width{ get; set; }
public double Height{ get; set; }
public int ScreenIndex{ get; set; }
public int PosX{ get; set; }
public int PosY{ get; set; }
}
public class ToastMessage(string message, ToastType type, int i){
public string? Message{ get; set; } = message;
public int Seconds{ get; set; } = i;
public ToastType Type{ get; set; } = type;
}
public class NavigationMessage{
public Type? ViewModelType{ get; }
public bool Back{ get; }
public bool Refresh{ get; }
public NavigationMessage(Type? viewModelType, bool back, bool refresh){
ViewModelType = viewModelType;
Back = back;
Refresh = refresh;
}
}

View File

@ -30,18 +30,28 @@ public partial class AccountPageViewModel : ViewModelBase{
private static DispatcherTimer? _timer;
private DateTime _targetTime;
private bool IsCancelled = false;
private bool UnknownEndDate = false;
private bool EndedButMaybeActive = false;
public AccountPageViewModel(){
UpdatetProfile();
}
private void Timer_Tick(object sender, EventArgs e){
var remaining = _targetTime - DateTime.UtcNow;
var remaining = _targetTime - DateTime.Now;
if (remaining <= TimeSpan.Zero){
RemainingTime = "No active Subscription";
_timer.Stop();
if (UnknownEndDate){
RemainingTime = "Unknown Subscription end date";
}
if (EndedButMaybeActive){
RemainingTime = "Subscription maybe ended";
}
if (CrunchyrollManager.Instance.Profile.Subscription != null){
Console.Error.WriteLine(JsonConvert.SerializeObject(CrunchyrollManager.Instance.Profile.Subscription, Formatting.Indented));
}
@ -51,25 +61,26 @@ public partial class AccountPageViewModel : ViewModelBase{
}
public void UpdatetProfile(){
ProfileName = CrunchyrollManager.Instance.Profile.Username; // Default or fetched user name
ProfileName = CrunchyrollManager.Instance.Profile.Username ?? "???"; // Default or fetched user name
LoginLogoutText = CrunchyrollManager.Instance.Profile.Username == "???" ? "Login" : "Logout"; // Default state
LoadProfileImage("https://static.crunchyroll.com/assets/avatar/170x170/" + CrunchyrollManager.Instance.Profile.Avatar);
if (CrunchyrollManager.Instance.Profile.Subscription != null && CrunchyrollManager.Instance.Profile.Subscription?.SubscriptionProducts != null){
if (CrunchyrollManager.Instance.Profile.Subscription?.SubscriptionProducts.Count >= 1){
var sub = CrunchyrollManager.Instance.Profile.Subscription?.SubscriptionProducts.First();
if (sub != null){
IsCancelled = sub.IsCancelled;
}
}else if (CrunchyrollManager.Instance.Profile.Subscription?.ThirdPartySubscriptionProducts.Count >= 1){
var sub = CrunchyrollManager.Instance.Profile.Subscription?.ThirdPartySubscriptionProducts.First();
if (sub != null){
IsCancelled = !sub.AutoRenew;
}
}else if(CrunchyrollManager.Instance.Profile.Subscription?.NonrecurringSubscriptionProducts.Count >= 1){
var subscriptions = CrunchyrollManager.Instance.Profile.Subscription;
if (subscriptions != null){
if (subscriptions.SubscriptionProducts is{ Count: >= 1 }){
var sub = subscriptions.SubscriptionProducts.First();
IsCancelled = sub.IsCancelled;
EndedButMaybeActive = !subscriptions.IsActive;
} else if (subscriptions.ThirdPartySubscriptionProducts is{ Count: >= 1 }){
var sub = subscriptions.ThirdPartySubscriptionProducts.First();
IsCancelled = !sub.AutoRenew;
EndedButMaybeActive = !subscriptions.IsActive;
} else if (subscriptions.NonrecurringSubscriptionProducts is{ Count: >= 1 }){
IsCancelled = true;
}else if(CrunchyrollManager.Instance.Profile.Subscription?.FunimationSubscriptions.Count >= 1){
EndedButMaybeActive = !subscriptions.IsActive;
} else if (subscriptions.FunimationSubscriptions is{ Count: >= 1 }){
IsCancelled = true;
UnknownEndDate = true;
}
@ -82,24 +93,27 @@ public partial class AccountPageViewModel : ViewModelBase{
_timer.Tick += Timer_Tick;
_timer.Start();
}
} else{
RemainingTime = "No active Subscription";
if (_timer != null){
_timer.Stop();
_timer.Tick -= Timer_Tick;
}
RaisePropertyChanged(nameof(RemainingTime));
if (CrunchyrollManager.Instance.Profile.Subscription != null){
Console.Error.WriteLine(JsonConvert.SerializeObject(CrunchyrollManager.Instance.Profile.Subscription, Formatting.Indented));
}
}
if (UnknownEndDate){
RemainingTime = "Unknown Subscription end date";
}
if (EndedButMaybeActive){
RemainingTime = "Subscription maybe ended";
}
}
[RelayCommand]

View File

@ -1,13 +1,20 @@
using System;
using System.Collections.Generic;
using System.IO;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Platform;
using CRD.Utils;
using CRD.Utils.Structs;
using CRD.Utils.Updater;
using CRD.ViewModels;
using CRD.Views;
using CRD.Views.Utils;
using FluentAvalonia.Core;
using FluentAvalonia.UI.Controls;
using FluentAvalonia.UI.Windowing;
using Newtonsoft.Json;
using ReactiveUI;
using ContentDialogUpdateViewModel = CRD.ViewModels.Utils.ContentDialogUpdateViewModel;
@ -44,7 +51,10 @@ public partial class MainWindow : AppWindow{
public MainWindow(){
AvaloniaXamlLoader.Load(this);
InitializeComponent();
Opened += OnOpened;
Closing += OnClosing;
TitleBar.ExtendsContentIntoTitleBar = true;
TitleBar.TitleBarHitTestType = TitleBarHitTestType.Complex;
@ -62,6 +72,7 @@ public partial class MainWindow : AppWindow{
if (viewModel is SeriesPageViewModel){
((SeriesPageViewModel)viewModel).SetStorageProvider(StorageProvider);
}
navigationStack.Push(viewModel);
nv.Content = viewModel;
} else if (!message.Back && message.ViewModelType != null){
@ -69,6 +80,7 @@ public partial class MainWindow : AppWindow{
if (viewModel is SeriesPageViewModel){
((SeriesPageViewModel)viewModel).SetStorageProvider(StorageProvider);
}
navigationStack.Push(viewModel);
nv.Content = viewModel;
} else{
@ -117,9 +129,10 @@ public partial class MainWindow : AppWindow{
break;
case "History":
navView.Content = Activator.CreateInstance(typeof(HistoryPageViewModel));
if ( navView.Content is HistoryPageViewModel){
if (navView.Content is HistoryPageViewModel){
((HistoryPageViewModel)navView.Content).SetStorageProvider(StorageProvider);
}
navigationStack.Clear();
navigationStack.Push(navView.Content);
selectedNavVieItem = selectedItem;
@ -159,22 +172,55 @@ public partial class MainWindow : AppWindow{
_ = await dialog.ShowAsync();
}
}
public class ToastMessage(string message, ToastType type, int i){
public string? Message{ get; set; } = message;
public int Seconds{ get; set; } = i;
public ToastType Type{ get; set; } = type;
}
private void OnOpened(object sender, EventArgs e){
if (File.Exists(CfgManager.PathWindowSettings)){
var settings = JsonConvert.DeserializeObject<WindowSettings>(File.ReadAllText(CfgManager.PathWindowSettings));
if (settings != null){
Width = settings.Width;
Height = settings.Height;
public class NavigationMessage{
public Type? ViewModelType{ get; }
public bool Back{ get; }
public bool Refresh{ get; }
var screens = Screens.All;
if (settings.ScreenIndex >= 0 && settings.ScreenIndex < screens.Count){
var screen = screens[settings.ScreenIndex];
var screenBounds = screen.Bounds;
public NavigationMessage(Type? viewModelType, bool back, bool refresh){
ViewModelType = viewModelType;
Back = back;
Refresh = refresh;
var topLeft = screenBounds.TopLeft;
var bottomRight = screenBounds.BottomRight;
if (settings.PosX >= topLeft.X && settings.PosX <= bottomRight.X - Width &&
settings.PosY >= topLeft.Y && settings.PosY <= bottomRight.Y - Height){
Position = new PixelPoint(settings.PosX, settings.PosY);
} else{
Position = new PixelPoint(topLeft.X, topLeft.Y + 31);
}
} else{
var primaryScreen = screens?[0].Bounds ?? new PixelRect(0, 0, 1000, 600); // Default size if no screens
Position = new PixelPoint(primaryScreen.TopLeft.X, primaryScreen.TopLeft.Y + 31);
}
}
}
}
private void OnClosing(object sender, System.ComponentModel.CancelEventArgs e){
var screens = Screens.All;
int screenIndex = 0;
for (int i = 0; i < screens.Count; i++){
if (screens[i].Bounds.Contains(Position)){
screenIndex = i;
break;
}
}
var settings = new WindowSettings{
Width = Width,
Height = Height,
ScreenIndex = screenIndex,
PosX = Position.X,
PosY = Position.Y
};
File.WriteAllText(CfgManager.PathWindowSettings, JsonConvert.SerializeObject(settings, Formatting.Indented));
}
}