diff --git a/back/src/Kyoo.Abstractions/Controllers/ILibraryManager.cs b/back/src/Kyoo.Abstractions/Controllers/ILibraryManager.cs
index ad4e6afe..ef5bd683 100644
--- a/back/src/Kyoo.Abstractions/Controllers/ILibraryManager.cs
+++ b/back/src/Kyoo.Abstractions/Controllers/ILibraryManager.cs
@@ -41,7 +41,7 @@ namespace Kyoo.Abstractions.Controllers
///
/// The repository that handle watched items.
///
- IWatchItemsRepository WatchItems { get; }
+ IWatchStatusRepository WatchStatus { get; }
///
/// The repository that handle collections.
diff --git a/back/src/Kyoo.Abstractions/Controllers/IRepository.cs b/back/src/Kyoo.Abstractions/Controllers/IRepository.cs
index b53d8c38..9665e091 100644
--- a/back/src/Kyoo.Abstractions/Controllers/IRepository.cs
+++ b/back/src/Kyoo.Abstractions/Controllers/IRepository.cs
@@ -88,10 +88,12 @@ namespace Kyoo.Abstractions.Controllers
/// A predicate to filter the resource.
/// The related fields to include.
/// A custom sort method to handle cases where multiples items match the filters.
+ /// Reverse the sort.
/// The resource found
Task GetOrDefault(Filter? filter,
Include? include = default,
- Sort? sortBy = default);
+ Sort? sortBy = default,
+ bool reverse = false);
///
/// Search for resources with the database.
diff --git a/back/src/Kyoo.Abstractions/Controllers/IWatchItemsRepository.cs b/back/src/Kyoo.Abstractions/Controllers/IWatchStatusRepository.cs
similarity index 58%
rename from back/src/Kyoo.Abstractions/Controllers/IWatchItemsRepository.cs
rename to back/src/Kyoo.Abstractions/Controllers/IWatchStatusRepository.cs
index 465bc838..0a60f458 100644
--- a/back/src/Kyoo.Abstractions/Controllers/IWatchItemsRepository.cs
+++ b/back/src/Kyoo.Abstractions/Controllers/IWatchStatusRepository.cs
@@ -26,7 +26,7 @@ namespace Kyoo.Abstractions.Controllers;
///
/// A local repository to handle watched items
///
-public interface IWatchItemsRepository : IBaseRepository
+public interface IWatchStatusRepository
{
// ///
// /// The event handler type for all events of this repository.
@@ -53,4 +53,40 @@ public interface IWatchItemsRepository : IBaseRepository
/// is
/// The movie's status
Task SetMovieStatus(int movieId, int userId, WatchStatus status, int? watchedTime);
+
+ ///
+ /// Get the watch status of a show.
+ ///
+ /// The show selector.
+ /// The id of the user.
+ /// The show's status
+ Task GetShowStatus(Expression> where, int userId);
+
+ ///
+ /// Set the watch status of a show.
+ ///
+ /// The id of the movie.
+ /// The id of the user.
+ /// The new status.
+ /// The shows's status
+ Task SetShowStatus(int showId, int userId, WatchStatus status);
+
+ ///
+ /// Get the watch status of an episode.
+ ///
+ /// The episode selector.
+ /// The id of the user.
+ /// The episode's status
+ Task GetEpisodeStatus(Expression> where, int userId);
+
+ ///
+ /// Set the watch status of an episode.
+ ///
+ /// The id of the episode.
+ /// The id of the user.
+ /// The new status.
+ /// Where the user has stopped watching. Only usable if Status
+ /// is
+ /// The episode's status
+ Task SetEpisodeStatus(int episodeId, int userId, WatchStatus status, int? watchedTime);
}
diff --git a/back/src/Kyoo.Core/Controllers/LibraryManager.cs b/back/src/Kyoo.Core/Controllers/LibraryManager.cs
index ad94977f..db52bd66 100644
--- a/back/src/Kyoo.Core/Controllers/LibraryManager.cs
+++ b/back/src/Kyoo.Core/Controllers/LibraryManager.cs
@@ -32,7 +32,7 @@ namespace Kyoo.Core.Controllers
public LibraryManager(
IRepository libraryItemRepository,
IRepository newsRepository,
- IWatchItemsRepository watchItemsRepository,
+ IWatchStatusRepository watchStatusRepository,
IRepository collectionRepository,
IRepository movieRepository,
IRepository showRepository,
@@ -44,7 +44,7 @@ namespace Kyoo.Core.Controllers
{
LibraryItems = libraryItemRepository;
News = newsRepository;
- WatchItems = watchItemsRepository;
+ WatchStatus = watchStatusRepository;
Collections = collectionRepository;
Movies = movieRepository;
Shows = showRepository;
@@ -58,7 +58,6 @@ namespace Kyoo.Core.Controllers
{
LibraryItems,
News,
- WatchItems,
Collections,
Movies,
Shows,
@@ -77,7 +76,7 @@ namespace Kyoo.Core.Controllers
public IRepository News { get; }
///
- public IWatchItemsRepository WatchItems { get; }
+ public IWatchStatusRepository WatchStatus { get; }
///
public IRepository Collections { get; }
diff --git a/back/src/Kyoo.Core/Controllers/Repositories/LocalRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/LocalRepository.cs
index 46aff561..4f69ca5f 100644
--- a/back/src/Kyoo.Core/Controllers/Repositories/LocalRepository.cs
+++ b/back/src/Kyoo.Core/Controllers/Repositories/LocalRepository.cs
@@ -257,13 +257,16 @@ namespace Kyoo.Core.Controllers
///
public virtual Task GetOrDefault(Filter? filter,
Include? include = default,
- Sort? sortBy = default)
+ Sort? sortBy = default,
+ bool reverse = false)
{
- return Sort(
- AddIncludes(Database.Set(), include),
- sortBy
- )
- .FirstOrDefaultAsync(ParseFilter(filter));
+ IQueryable query = Sort(
+ AddIncludes(Database.Set(), include),
+ sortBy
+ );
+ if (reverse)
+ query = query.Reverse();
+ return query.FirstOrDefaultAsync(ParseFilter(filter));
}
///
diff --git a/back/src/Kyoo.Core/Controllers/Repositories/WatchItemsRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/WatchItemsRepository.cs
deleted file mode 100644
index c2974767..00000000
--- a/back/src/Kyoo.Core/Controllers/Repositories/WatchItemsRepository.cs
+++ /dev/null
@@ -1,68 +0,0 @@
-// Kyoo - A portable and vast media library solution.
-// Copyright (c) Kyoo.
-//
-// See AUTHORS.md and LICENSE file in the project root for full license information.
-//
-// Kyoo is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// any later version.
-//
-// Kyoo is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Kyoo. If not, see .
-
-using System;
-using System.ComponentModel.DataAnnotations;
-using System.Linq;
-using System.Linq.Expressions;
-using System.Threading.Tasks;
-using Kyoo.Abstractions.Controllers;
-using Kyoo.Abstractions.Models;
-using Kyoo.Postgresql;
-using Microsoft.EntityFrameworkCore;
-
-namespace Kyoo.Core.Controllers;
-
-public class WatchItemsRepository : IWatchItemsRepository
-{
- private readonly DatabaseContext _database;
-
- public WatchItemsRepository(DatabaseContext database)
- {
- _database = database;
- }
-
- ///
- public Task GetMovieStatus(Expression> where, int userId)
- {
- return _database.MovieWatchInfo.FirstOrDefaultAsync(x =>
- x.Movie == _database.Movies.FirstOrDefault(where)
- && x.UserId == userId
- );
- }
-
- ///
- public async Task SetMovieStatus(
- int movieId,
- int userId,
- WatchStatus status,
- int? watchedTime)
- {
- if (watchedTime.HasValue && status != WatchStatus.Watching)
- throw new ValidationException("Can't have a watched time if the status is not watching.");
- MovieWatchStatus ret = new()
- {
- UserId = userId,
- MovieId = movieId,
- Status = status,
- WatchedTime = watchedTime,
- };
- await _database.MovieWatchInfo.Upsert(ret).RunAsync();
- return ret;
- }
-}
diff --git a/back/src/Kyoo.Core/Controllers/Repositories/WatchStatusRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/WatchStatusRepository.cs
new file mode 100644
index 00000000..743e5e64
--- /dev/null
+++ b/back/src/Kyoo.Core/Controllers/Repositories/WatchStatusRepository.cs
@@ -0,0 +1,138 @@
+// Kyoo - A portable and vast media library solution.
+// Copyright (c) Kyoo.
+//
+// See AUTHORS.md and LICENSE file in the project root for full license information.
+//
+// Kyoo is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// any later version.
+//
+// Kyoo is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Kyoo. If not, see .
+
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Threading.Tasks;
+using Kyoo.Abstractions.Controllers;
+using Kyoo.Abstractions.Models;
+using Kyoo.Postgresql;
+using Microsoft.EntityFrameworkCore;
+
+namespace Kyoo.Core.Controllers;
+
+public class WatchStatusRepository : IWatchStatusRepository
+{
+ private readonly DatabaseContext _database;
+ private readonly IRepository _episodes;
+
+ public WatchStatusRepository(DatabaseContext database, IRepository episodes)
+ {
+ _database = database;
+ _episodes = episodes;
+ }
+
+ ///
+ public Task GetMovieStatus(Expression> where, int userId)
+ {
+ return _database.MovieWatchInfo.FirstOrDefaultAsync(x =>
+ x.Movie == _database.Movies.FirstOrDefault(where)
+ && x.UserId == userId
+ );
+ }
+
+ ///
+ public async Task SetMovieStatus(
+ int movieId,
+ int userId,
+ WatchStatus status,
+ int? watchedTime)
+ {
+ if (watchedTime.HasValue && status != WatchStatus.Watching)
+ throw new ValidationException("Can't have a watched time if the status is not watching.");
+ MovieWatchStatus ret = new()
+ {
+ UserId = userId,
+ MovieId = movieId,
+ Status = status,
+ WatchedTime = watchedTime,
+ };
+ await _database.MovieWatchInfo.Upsert(ret)
+ .UpdateIf(x => !(status == WatchStatus.Watching && x.Status == WatchStatus.Completed))
+ .RunAsync();
+ return ret;
+ }
+
+ ///
+ public Task GetShowStatus(Expression> where, int userId)
+ {
+ return _database.ShowWatchInfo.FirstOrDefaultAsync(x =>
+ x.Show == _database.Shows.FirstOrDefault(where)
+ && x.UserId == userId
+ );
+ }
+
+ ///
+ public async Task SetShowStatus(
+ int showId,
+ int userId,
+ WatchStatus status)
+ {
+ ShowWatchStatus ret = new()
+ {
+ UserId = userId,
+ ShowId = showId,
+ Status = status,
+ NextEpisode = status == WatchStatus.Watching
+ ? await _episodes.GetOrDefault(
+ where: x => x.ShowId == showId
+ && (x.WatchStatus!.Status == WatchStatus.Watching
+ || x.WatchStatus.Status == WatchStatus.Completed),
+ reverse: true
+ )
+ : null,
+ };
+ await _database.ShowWatchInfo.Upsert(ret)
+ .UpdateIf(x => !(status == WatchStatus.Watching && x.Status == WatchStatus.Completed))
+ .RunAsync();
+ return ret;
+ }
+
+ ///
+ public Task GetEpisodeStatus(Expression> where, int userId)
+ {
+ return _database.EpisodeWatchInfo.FirstOrDefaultAsync(x =>
+ x.Episode == _database.Episodes.FirstOrDefault(where)
+ && x.UserId == userId
+ );
+ }
+
+ ///
+ public async Task SetEpisodeStatus(
+ int episodeId,
+ int userId,
+ WatchStatus status,
+ int? watchedTime)
+ {
+ Episode episode = await _episodes.Get(episodeId);
+ if (watchedTime.HasValue && status != WatchStatus.Watching)
+ throw new ValidationException("Can't have a watched time if the status is not watching.");
+ EpisodeWatchStatus ret = new()
+ {
+ UserId = userId,
+ EpisodeId = episodeId,
+ Status = status,
+ WatchedTime = watchedTime,
+ };
+ await _database.EpisodeWatchInfo.Upsert(ret).RunAsync();
+ await SetShowStatus(episode.ShowId, userId, WatchStatus.Watching);
+ return ret;
+ }
+}
diff --git a/back/src/Kyoo.Core/Views/Resources/MovieApi.cs b/back/src/Kyoo.Core/Views/Resources/MovieApi.cs
index 5aec36b3..eca3006d 100644
--- a/back/src/Kyoo.Core/Views/Resources/MovieApi.cs
+++ b/back/src/Kyoo.Core/Views/Resources/MovieApi.cs
@@ -170,7 +170,7 @@ namespace Kyoo.Core.Api
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task GetWatchStatus(Identifier identifier)
{
- return await _libraryManager.WatchItems.GetMovieStatus(
+ return await _libraryManager.WatchStatus.GetMovieStatus(
identifier.IsSame(),
User.GetId()!.Value
);
@@ -202,7 +202,7 @@ namespace Kyoo.Core.Api
id => Task.FromResult(id),
async slug => (await _libraryManager.Movies.Get(slug)).Id
);
- return await _libraryManager.WatchItems.SetMovieStatus(
+ return await _libraryManager.WatchStatus.SetMovieStatus(
id,
User.GetId()!.Value,
status,