Add every tables for watchlists

This commit is contained in:
Zoe Roux 2023-11-12 19:30:07 +01:00
parent 4135fc5703
commit b6bb190e69
7 changed files with 151 additions and 25 deletions

View File

@ -28,7 +28,10 @@
<Rule Id="SA1027" Action="None"/> <!-- UseTabsCorrectly (smarts tabs are broken). TODO find a way to enable smart tabs -->
</Rules>
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.LayoutRules">
<Rule Id="SA1402" Action="None"/> <!-- SingleClassPerFile -->
<Rule Id="SA1649" Action="None"/> <!-- Class name must be filename -->
<Rule Id="SA1503" Action="None"/> <!-- BracesMustNotBeOmitted -->
<Rule Id="SA1512" Action="None"/> <!-- Let me comment -->
<Rule Id="SA1520" Action="None"/> <!-- UseBracesConsistently -->
<Rule Id="SA1515" Action="None"/> <!-- SingleLineCommentMustBePrecededByBlankLine -->
<Rule Id="SA1513" Action="None"/> <!-- ClosingBraceMustBeFollowedByBlankLine -->

View File

@ -238,6 +238,17 @@ namespace Kyoo.Abstractions.Models
|| (x.SeasonNumber == SeasonNumber && x.EpisodeNumber > EpisodeNumber)
);
[SerializeIgnore] public ICollection<EpisodeWatchInfo> Watched { get; set; }
/// <summary>
/// Metadata of what an user as started/planned to watch.
/// </summary>
[Projectable(UseMemberBody = nameof(_WatchInfo), OnlyOnInclude = true)]
[LoadableRelation] public EpisodeWatchInfo? WatchInfo { get; set; }
// There is a global query filter to filter by user so we just need to do single.
private EpisodeWatchInfo? _WatchInfo => Watched.FirstOrDefault();
/// <summary>
/// Links to watch this episode.
/// </summary>

View File

@ -146,16 +146,16 @@ namespace Kyoo.Abstractions.Models
Hls = $"/video/movie/{Slug}/master.m3u8",
};
[SerializeIgnore] public ICollection<WatchInfo> Watched { get; set; }
[SerializeIgnore] public ICollection<MovieWatchInfo> Watched { get; set; }
/// <summary>
/// Metadata of what an user as started/planned to watch.
/// </summary>
[Projectable(UseMemberBody = nameof(_WatchInfo), OnlyOnInclude = true)]
[LoadableRelation] public WatchInfo? WatchInfo { get; set; }
[LoadableRelation] public MovieWatchInfo? WatchInfo { get; set; }
// There is a global query filter to filter by user so we just need to do single.
private WatchInfo? _WatchInfo => Watched.FirstOrDefault();
private MovieWatchInfo? _WatchInfo => Watched.FirstOrDefault();
/// <inheritdoc />
public void OnMerge(object merged)

View File

@ -178,6 +178,17 @@ namespace Kyoo.Abstractions.Models
.ThenBy(x => x.EpisodeNumber)
.FirstOrDefault();
[SerializeIgnore] public ICollection<ShowWatchInfo> Watched { get; set; }
/// <summary>
/// Metadata of what an user as started/planned to watch.
/// </summary>
[Projectable(UseMemberBody = nameof(_WatchInfo), OnlyOnInclude = true)]
[LoadableRelation] public ShowWatchInfo? WatchInfo { get; set; }
// There is a global query filter to filter by user so we just need to do single.
private ShowWatchInfo? _WatchInfo => Watched.FirstOrDefault();
/// <inheritdoc />
public void OnMerge(object merged)
{

View File

@ -69,11 +69,11 @@ namespace Kyoo.Abstractions.Models
/// </summary>
public Image? Logo { get; set; }
/// <summary>
/// The user's watch list.
/// </summary>
[SerializeIgnore]
public ICollection<WatchInfo>? Watchlist { get; set; }
// /// <summary>
// /// The user's watch list.
// /// </summary>
// // [SerializeIgnore]
// // public ICollection<WatchInfo>? Watchlist { get; set; }
public User() { }

View File

@ -17,6 +17,8 @@
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
using System;
using System.Linq;
using EntityFrameworkCore.Projectables;
using Kyoo.Abstractions.Models.Attributes;
namespace Kyoo.Abstractions.Models
@ -50,7 +52,46 @@ namespace Kyoo.Abstractions.Models
/// <summary>
/// Metadata of what an user as started/planned to watch.
/// </summary>
public class WatchInfo : IAddedDate
public class MovieWatchInfo : IAddedDate
{
/// <summary>
/// The ID of the user that started watching this episode.
/// </summary>
[SerializeIgnore] public Guid UserId { get; set; }
/// <summary>
/// The user that started watching this episode.
/// </summary>
[SerializeIgnore] public User User { get; set; }
/// <summary>
/// The ID of the movie started.
/// </summary>
[SerializeIgnore] public Guid MovieId { get; set; }
/// <summary>
/// The <see cref="Movie"/> started.
/// </summary>
[SerializeIgnore] public Movie Movie { get; set; }
/// <inheritdoc/>
public DateTime AddedDate { get; set; }
/// <summary>
/// Has the user started watching, is it planned?
/// </summary>
public WatchStatus Status { get; set; }
/// <summary>
/// Where the player has stopped watching the movie (in seconds).
/// </summary>
/// <remarks>
/// Null if the status is not Watching.
/// </remarks>
public int? WatchedTime { get; set; }
}
public class EpisodeWatchInfo : IAddedDate
{
/// <summary>
/// The ID of the user that started watching this episode.
@ -70,20 +111,10 @@ namespace Kyoo.Abstractions.Models
/// <summary>
/// The <see cref="Episode"/> started.
/// </summary>
[SerializeIgnore] public Episode? Episode { get; set; }
/// <summary>
/// The ID of the movie started.
/// </summary>
[SerializeIgnore] public Guid? MovieId { get; set; }
/// <summary>
/// The <see cref="Movie"/> started.
/// </summary>
[SerializeIgnore] public Movie? Movie { get; set; }
[SerializeIgnore] public Episode Episode { get; set; }
/// <inheritdoc/>
[SerializeIgnore] public DateTime AddedDate { get; set; }
public DateTime AddedDate { get; set; }
/// <summary>
/// Has the user started watching, is it planned?
@ -98,4 +129,56 @@ namespace Kyoo.Abstractions.Models
/// </remarks>
public int? WatchedTime { get; set; }
}
public class ShowWatchInfo : IAddedDate
{
/// <summary>
/// The ID of the user that started watching this episode.
/// </summary>
[SerializeIgnore] public Guid UserId { get; set; }
/// <summary>
/// The user that started watching this episode.
/// </summary>
[SerializeIgnore] public User User { get; set; }
/// <summary>
/// The ID of the show started.
/// </summary>
[SerializeIgnore] public Guid ShowId { get; set; }
/// <summary>
/// The <see cref="Show"/> started.
/// </summary>
[SerializeIgnore] public Show Show { get; set; }
/// <inheritdoc/>
public DateTime AddedDate { get; set; }
/// <summary>
/// Has the user started watching, is it planned?
/// </summary>
public WatchStatus Status { get; set; }
/// <summary>
/// The ID of the episode started.
/// </summary>
[SerializeIgnore] public Guid NextEpisodeId { get; set; }
/// <summary>
/// The <see cref="Show"/> started.
/// </summary>
public Episode? NextEpisode { get; set; }
/// <summary>
/// Where the player has stopped watching the episode (in seconds).
/// </summary>
/// <remarks>
/// Null if the status is not Watching or if the next episode is not started.
/// </remarks>
[Projectable(UseMemberBody = nameof(_WatchedTime), NullConditionalRewriteSupport = NullConditionalRewriteSupport.Ignore)]
public int? WatchedTime { get; set; }
private int? _WatchedTime => NextEpisode?.Watched.FirstOrDefault()?.WatchedTime;
}
}

View File

@ -100,7 +100,11 @@ namespace Kyoo.Postgresql
// /// </summary>
// public DbSet<PeopleRole> PeopleRoles { get; set; }
public DbSet<WatchInfo> WatchInfo { get; set; }
public DbSet<MovieWatchInfo> MovieWatchInfo { get; set; }
public DbSet<ShowWatchInfo> ShowWatchInfo { get; set; }
public DbSet<EpisodeWatchInfo> EpisodeWatchInfo { get; set; }
/// <summary>
/// Add a many to many link between two resources.
@ -302,10 +306,24 @@ namespace Kyoo.Postgresql
modelBuilder.Entity<User>().OwnsOne(x => x.Logo);
modelBuilder.Entity<WatchInfo>()
.HasKey(x => new { User = x.UserId, Episode = x.EpisodeId, Movie = x.MovieId });
modelBuilder.Entity<WatchInfo>().HasQueryFilter(x => x.UserId == CurrentUserId);
modelBuilder.Entity<MovieWatchInfo>()
.HasKey(x => new { User = x.UserId, Movie = x.MovieId });
modelBuilder.Entity<ShowWatchInfo>()
.HasKey(x => new { User = x.UserId, Show = x.ShowId });
modelBuilder.Entity<EpisodeWatchInfo>()
.HasKey(x => new { User = x.UserId, Episode = x.EpisodeId });
modelBuilder.Entity<MovieWatchInfo>().HasQueryFilter(x => x.UserId == CurrentUserId);
modelBuilder.Entity<ShowWatchInfo>().HasQueryFilter(x => x.UserId == CurrentUserId);
modelBuilder.Entity<EpisodeWatchInfo>().HasQueryFilter(x => x.UserId == CurrentUserId);
_HasAddedDate<MovieWatchInfo>(modelBuilder);
_HasAddedDate<ShowWatchInfo>(modelBuilder);
_HasAddedDate<EpisodeWatchInfo>(modelBuilder);
modelBuilder.Entity<Movie>().Ignore(x => x.WatchInfo);
modelBuilder.Entity<Show>().Ignore(x => x.WatchInfo);
modelBuilder.Entity<Episode>().Ignore(x => x.WatchInfo);
modelBuilder.Entity<Collection>()
.HasIndex(x => x.Slug)