diff --git a/Totoro.Core/Contracts/IMyAnimeListService.cs b/Totoro.Core/Contracts/IMyAnimeListService.cs index 1fea8e7..97afe44 100644 --- a/Totoro.Core/Contracts/IMyAnimeListService.cs +++ b/Totoro.Core/Contracts/IMyAnimeListService.cs @@ -3,6 +3,7 @@ public interface IMyAnimeListService { Task> GetEpisodes(long id); + IAsyncEnumerable GetFillers(long id); IObservable> GetAiringAnime(); IObservable> GetUpcomingAnime(); IObservable> GetPopularAnime(); diff --git a/Totoro.Core/Models/EpisodeModel.cs b/Totoro.Core/Models/EpisodeModel.cs index 49b61d2..c2b66d9 100644 --- a/Totoro.Core/Models/EpisodeModel.cs +++ b/Totoro.Core/Models/EpisodeModel.cs @@ -10,6 +10,7 @@ public class EpisodeModel : ReactiveObject [Reactive] public string SpecialEpisodeNumber { get; set; } [Reactive] public bool IsSpecial { get; set; } [Reactive] public string EpisodeTitle { get; set; } + [Reactive] public bool IsFillter { get; set; } [ObservableAsProperty] public string DisplayName { get; } public EpisodeModel() diff --git a/Totoro.Core/Services/MyAnimeList/MyAnimeListService.cs b/Totoro.Core/Services/MyAnimeList/MyAnimeListService.cs index ddb628b..25c1320 100644 --- a/Totoro.Core/Services/MyAnimeList/MyAnimeListService.cs +++ b/Totoro.Core/Services/MyAnimeList/MyAnimeListService.cs @@ -1,27 +1,24 @@ -using JikanDotNet; +using System.Collections.Generic; +using AngleSharp.Io; +using JikanDotNet; using MalApi; using MalApi.Interfaces; using static Totoro.Core.Services.MyAnimeList.MalToModelConverter; namespace Totoro.Core.Services.MyAnimeList; -public class MyAnimeListService : IAnimeService, IMyAnimeListService +public class MyAnimeListService(IMalClient client, + IAnilistService anilistService, + IAnimeIdService animeIdService, + ISettings settings) : IAnimeService, IMyAnimeListService { - private readonly IMalClient _client; - private readonly IAnilistService _anilistService; - private readonly ISettings _settings; + private readonly IMalClient _client = client; + private readonly IAnilistService _anilistService = anilistService; + private readonly IAnimeIdService _animeIdService = animeIdService; + private readonly ISettings _settings = settings; private readonly IJikan _jikan = new Jikan(); private readonly string _recursiveAnimeProperties = $"my_list_status,status,{AnimeFieldNames.TotalEpisodes},{AnimeFieldNames.Mean}"; - public MyAnimeListService(IMalClient client, - IAnilistService anilistService, - ISettings settings) - { - _client = client; - _anilistService = anilistService; - _settings = settings; - } - public ListServiceType Type => ListServiceType.MyAnimeList; public IObservable GetInformation(long id) @@ -159,10 +156,35 @@ public async Task> GetEpisodes(long id) } catch { - return Enumerable.Empty(); + return []; } } + public async IAsyncEnumerable GetFillers(long id) + { + var animeId = await _animeIdService.GetId(id); + + if (animeId is null || animeId.MyAnimeList is null) + { + yield break; + } + + PaginatedJikanResponse> response = null; + var currentPage = 1; + var offset = 0; + do + { + response = await _jikan.GetAnimeEpisodesAsync(animeId.MyAnimeList.Value, currentPage++); + foreach (var item in response.Data.Select((x, index) => (x, index)).Where(x => x.x.Filler == true).Select(x => x.index + 1 + offset)) + { + yield return item; + } + + offset += response.Data.Count; + + } while (response.Pagination.HasNextPage); + } + private static MalApi.Season PrevSeason() { var date = DateTime.Now; diff --git a/Totoro.Core/ViewModels/WatchViewModel.cs b/Totoro.Core/ViewModels/WatchViewModel.cs index a4a7130..d591eba 100644 --- a/Totoro.Core/ViewModels/WatchViewModel.cs +++ b/Totoro.Core/ViewModels/WatchViewModel.cs @@ -41,6 +41,7 @@ public partial class WatchViewModel : NavigatableViewModel private readonly ISimklService _simklService; private readonly IAnimeDetectionService _animeDetectionService; private readonly IAnimePreferencesService _preferencesService; + private readonly IMyAnimeListService _myAnimeListService; private readonly List _mediaEventListeners; private readonly string[] _subDubProviders = ["gogo-anime", "anime-saturn"]; @@ -64,7 +65,8 @@ public WatchViewModel(IPluginFactory providerFactory, ISimklService simklService, IEnumerable mediaEventListeners, IAnimeDetectionService animeDetectionService, - IAnimePreferencesService preferencesService) + IAnimePreferencesService preferencesService, + IMyAnimeListService myAnimeListService) { _providerFactory = providerFactory; _viewService = viewService; @@ -77,6 +79,7 @@ public WatchViewModel(IPluginFactory providerFactory, _simklService = simklService; _animeDetectionService = animeDetectionService; _preferencesService = preferencesService; + _myAnimeListService = myAnimeListService; _mediaEventListeners = mediaEventListeners.ToList(); NextEpisode = ReactiveCommand.Create(() => @@ -115,7 +118,7 @@ public WatchViewModel(IPluginFactory providerFactory, this.ObservableForProperty(x => x.Anime, x => x) .WhereNotNull() - .Do(async model => _episodeMetadata ??= await simklService.GetEpisodes(model.Id)) + .Do(async model => await UpdateMetaData(model.Id)) .SelectMany(model => Find(model.Id, model.Title)) .Where(x => x is not (null, null)) .Log(this, "Selected Anime", x => $"{x.Sub.Title}") @@ -154,18 +157,7 @@ public WatchViewModel(IPluginFactory providerFactory, this.WhenAnyValue(x => x.EpisodeModels) .Where(x => x is not null && Anime is not null && _episodeMetadata is not null) .ObserveOn(RxApp.MainThreadScheduler) - .Subscribe(_ => - { - foreach (var item in _episodeMetadata) - { - if (EpisodeModels.FirstOrDefault(x => x.EpisodeNumber == item.EpisodeNumber) is not { } ep) - { - continue; - } - - ep.EpisodeTitle = item.EpisodeTitle; - } - }); + .Subscribe(_ => UpdateMetaData()); this.WhenAnyValue(x => x.EpisodeModels) .WhereNotNull() @@ -631,7 +623,7 @@ private void SetAnime(long id) .Subscribe(async anime => { _anime = anime; - _episodeMetadata = await _simklService.GetEpisodes(id); + await UpdateMetaData(id); SetAnime(_anime); }, RxApp.DefaultExceptionHandler.OnError); } @@ -760,4 +752,39 @@ private Task GetTimeStamps(TimeSpan duration) ? _timestampsService.GetTimeStampsWithMalId(malId, EpisodeModels.Current.EpisodeNumber, duration.TotalSeconds) : _timestampsService.GetTimeStampsWithMalId(Anime.Id, EpisodeModels.Current.EpisodeNumber, duration.TotalSeconds); } + + private void UpdateMetaData() + { + foreach (var item in _episodeMetadata) + { + if (EpisodeModels.FirstOrDefault(x => x.EpisodeNumber == item.EpisodeNumber) is not { } ep) + { + continue; + } + + ep.EpisodeTitle = item.EpisodeTitle; + ep.IsFillter = item.IsFillter; + } + } + + private async Task UpdateMetaData(long id) + { + var meta = (await _simklService.GetEpisodes(id)).ToList(); + var fillers = await _myAnimeListService.GetFillers(Anime.Id).ToListAsync(); + + foreach (var item in meta) + { + if(fillers.Contains(item.EpisodeNumber)) + { + item.IsFillter = true; + } + } + + _episodeMetadata = meta; + + if(EpisodeModels is not null) + { + UpdateMetaData(); + } + } } \ No newline at end of file diff --git a/Totoro.WinUI/Views/WatchPage.xaml b/Totoro.WinUI/Views/WatchPage.xaml index 69f8266..ce1bf3d 100644 --- a/Totoro.WinUI/Views/WatchPage.xaml +++ b/Totoro.WinUI/Views/WatchPage.xaml @@ -117,6 +117,7 @@ diff --git a/Totoro.WinUI/Views/WatchPage.xaml.cs b/Totoro.WinUI/Views/WatchPage.xaml.cs index edee805..7f6f029 100644 --- a/Totoro.WinUI/Views/WatchPage.xaml.cs +++ b/Totoro.WinUI/Views/WatchPage.xaml.cs @@ -1,14 +1,15 @@ using System.Data; +using Microsoft.UI; using Microsoft.UI.Input; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Media; using ReactiveMarbles.ObservableEvents; using Totoro.Core.ViewModels; using Totoro.WinUI.Contracts; using Totoro.WinUI.Media.Flyleaf; using Totoro.WinUI.Media.Wmp; using Totoro.WinUI.UserControls; -using WinUIEx; namespace Totoro.WinUI.Views; @@ -143,6 +144,13 @@ private void EnterPiPMode() }; } + public static SolidColorBrush Foreground(bool isFiller) + { + return isFiller + ? new SolidColorBrush(Colors.Yellow) + : new SolidColorBrush(Colors.White); + } + private string GetWindowTitle() { if(ViewModel.Anime is null)