mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Make runtime nullable
This commit is contained in:
parent
b6df0ba2b1
commit
c0e6012d70
@ -48,7 +48,8 @@ public interface IWatchStatusRepository
|
||||
Guid movieId,
|
||||
Guid userId,
|
||||
WatchStatus status,
|
||||
int? watchedTime
|
||||
int? watchedTime,
|
||||
int? percent
|
||||
);
|
||||
|
||||
Task DeleteMovieStatus(Guid movieId, Guid userId);
|
||||
@ -67,7 +68,8 @@ public interface IWatchStatusRepository
|
||||
Guid episodeId,
|
||||
Guid userId,
|
||||
WatchStatus status,
|
||||
int? watchedTime
|
||||
int? watchedTime,
|
||||
int? percent
|
||||
);
|
||||
|
||||
Task DeleteEpisodeStatus(Guid episodeId, Guid userId);
|
||||
|
@ -152,7 +152,7 @@ namespace Kyoo.Abstractions.Models
|
||||
/// <summary>
|
||||
/// How long is this episode? (in minutes)
|
||||
/// </summary>
|
||||
public int Runtime { get; set; }
|
||||
public int? Runtime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The release date of this episode. It can be null if unknown.
|
||||
|
@ -99,7 +99,7 @@ namespace Kyoo.Abstractions.Models
|
||||
/// <summary>
|
||||
/// How long is this movie? (in minutes)
|
||||
/// </summary>
|
||||
public int Runtime { get; set; }
|
||||
public int? Runtime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The date this movie aired.
|
||||
|
@ -236,14 +236,14 @@ public class WatchStatusRepository : IWatchStatusRepository
|
||||
Guid movieId,
|
||||
Guid userId,
|
||||
WatchStatus status,
|
||||
int? watchedTime
|
||||
int? watchedTime,
|
||||
int? percent
|
||||
)
|
||||
{
|
||||
Movie movie = await _movies.Get(movieId);
|
||||
int? percent =
|
||||
watchedTime != null && movie.Runtime > 0
|
||||
? (int)Math.Round(watchedTime.Value / (movie.Runtime * 60f) * 100f)
|
||||
: null;
|
||||
|
||||
if (percent == null && watchedTime != null && movie.Runtime > 0)
|
||||
percent = (int)Math.Round(watchedTime.Value / (movie.Runtime.Value * 60f) * 100f);
|
||||
|
||||
if (percent < MinWatchPercent)
|
||||
return null;
|
||||
@ -259,6 +259,12 @@ public class WatchStatusRepository : IWatchStatusRepository
|
||||
"Can't have a watched time if the status is not watching."
|
||||
);
|
||||
|
||||
if (watchedTime.HasValue != percent.HasValue)
|
||||
throw new ValidationException(
|
||||
"Can't specify watched time without specifing percent (or vise-versa)."
|
||||
+ "Percent could not be guessed since duration is unknown."
|
||||
);
|
||||
|
||||
MovieWatchStatus ret =
|
||||
new()
|
||||
{
|
||||
@ -463,14 +469,14 @@ public class WatchStatusRepository : IWatchStatusRepository
|
||||
Guid episodeId,
|
||||
Guid userId,
|
||||
WatchStatus status,
|
||||
int? watchedTime
|
||||
int? watchedTime,
|
||||
int? percent
|
||||
)
|
||||
{
|
||||
Episode episode = await _database.Episodes.FirstAsync(x => x.Id == episodeId);
|
||||
int? percent =
|
||||
watchedTime != null && episode.Runtime > 0
|
||||
? (int)Math.Round(watchedTime.Value / (episode.Runtime * 60f) * 100f)
|
||||
: null;
|
||||
|
||||
if (percent == null && watchedTime != null && episode.Runtime > 0)
|
||||
percent = (int)Math.Round(watchedTime.Value / (episode.Runtime.Value * 60f) * 100f);
|
||||
|
||||
if (percent < MinWatchPercent)
|
||||
return null;
|
||||
@ -486,6 +492,12 @@ public class WatchStatusRepository : IWatchStatusRepository
|
||||
"Can't have a watched time if the status is not watching."
|
||||
);
|
||||
|
||||
if (watchedTime.HasValue != percent.HasValue)
|
||||
throw new ValidationException(
|
||||
"Can't specify watched time without specifing percent (or vise-versa)."
|
||||
+ "Percent could not be guessed since duration is unknown."
|
||||
);
|
||||
|
||||
EpisodeWatchStatus ret =
|
||||
new()
|
||||
{
|
||||
|
@ -147,7 +147,8 @@ namespace Kyoo.Core.Api
|
||||
/// </remarks>
|
||||
/// <param name="identifier">The ID or slug of the <see cref="Episode"/>.</param>
|
||||
/// <param name="status">The new watch status.</param>
|
||||
/// <param name="watchedTime">Where the user stopped watching.</param>
|
||||
/// <param name="watchedTime">Where the user stopped watching (in seconds).</param>
|
||||
/// <param name="percent">Where the user stopped watching (in percent).</param>
|
||||
/// <returns>The newly set status.</returns>
|
||||
/// <response code="200">The status has been set</response>
|
||||
/// <response code="204">The status was not considered impactfull enough to be saved (less then 5% of watched for example).</response>
|
||||
@ -161,7 +162,8 @@ namespace Kyoo.Core.Api
|
||||
public async Task<EpisodeWatchStatus?> SetWatchStatus(
|
||||
Identifier identifier,
|
||||
WatchStatus status,
|
||||
int? watchedTime
|
||||
int? watchedTime,
|
||||
int? percent
|
||||
)
|
||||
{
|
||||
Guid id = await identifier.Match(
|
||||
@ -170,7 +172,7 @@ namespace Kyoo.Core.Api
|
||||
);
|
||||
return await _libraryManager
|
||||
.WatchStatus
|
||||
.SetEpisodeStatus(id, User.GetIdOrThrow(), status, watchedTime);
|
||||
.SetEpisodeStatus(id, User.GetIdOrThrow(), status, watchedTime, percent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -196,6 +196,7 @@ namespace Kyoo.Core.Api
|
||||
/// <param name="identifier">The ID or slug of the <see cref="Movie"/>.</param>
|
||||
/// <param name="status">The new watch status.</param>
|
||||
/// <param name="watchedTime">Where the user stopped watching.</param>
|
||||
/// <param name="percent">Where the user stopped watching (in percent).</param>
|
||||
/// <returns>The newly set status.</returns>
|
||||
/// <response code="200">The status has been set</response>
|
||||
/// <response code="204">The status was not considered impactfull enough to be saved (less then 5% of watched for example).</response>
|
||||
@ -210,7 +211,8 @@ namespace Kyoo.Core.Api
|
||||
public async Task<MovieWatchStatus?> SetWatchStatus(
|
||||
Identifier identifier,
|
||||
WatchStatus status,
|
||||
int? watchedTime
|
||||
int? watchedTime,
|
||||
int? percent
|
||||
)
|
||||
{
|
||||
Guid id = await identifier.Match(
|
||||
@ -219,7 +221,7 @@ namespace Kyoo.Core.Api
|
||||
);
|
||||
return await _libraryManager
|
||||
.WatchStatus
|
||||
.SetMovieStatus(id, User.GetIdOrThrow(), status, watchedTime);
|
||||
.SetMovieStatus(id, User.GetIdOrThrow(), status, watchedTime, percent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -49,7 +49,7 @@ export const BaseEpisodeP = withImages(
|
||||
/**
|
||||
* How long is this movie? (in minutes).
|
||||
*/
|
||||
runtime: z.number().int(),
|
||||
runtime: z.number().int().nullable(),
|
||||
/**
|
||||
* The release date of this episode. It can be null if unknown.
|
||||
*/
|
||||
|
@ -61,7 +61,7 @@ export const MovieP = withImages(
|
||||
/**
|
||||
* How long is this movie? (in minutes).
|
||||
*/
|
||||
runtime: z.number().int(),
|
||||
runtime: z.number().int().nullable(),
|
||||
/**
|
||||
* The date this movie aired. It can also be null if this is unknown.
|
||||
*/
|
||||
|
@ -106,6 +106,10 @@ export const WatchInfoP = z.object({
|
||||
* The sha1 of the video file.
|
||||
*/
|
||||
sha: z.string(),
|
||||
/**
|
||||
* The duration of the video (in seconds).
|
||||
*/
|
||||
length: z.number(),
|
||||
/**
|
||||
* The internal path of the video file.
|
||||
*/
|
||||
|
@ -57,7 +57,8 @@ export const episodeDisplayNumber = (
|
||||
return def;
|
||||
};
|
||||
|
||||
export const displayRuntime = (runtime: number) => {
|
||||
export const displayRuntime = (runtime: number | null) => {
|
||||
if (!runtime) return null;
|
||||
if (runtime < 60) return `${runtime}min`;
|
||||
return `${Math.floor(runtime / 60)}h${runtime % 60}`;
|
||||
};
|
||||
@ -300,8 +301,6 @@ export const EpisodeLine = ({
|
||||
)}
|
||||
</Skeleton>
|
||||
<View {...css({ flexDirection: "row", alignItems: "center" })}>
|
||||
{isLoading ||
|
||||
(runtime && (
|
||||
<Skeleton>
|
||||
{isLoading || (
|
||||
<SubP>
|
||||
@ -315,7 +314,6 @@ export const EpisodeLine = ({
|
||||
</SubP>
|
||||
)}
|
||||
</Skeleton>
|
||||
))}
|
||||
{slug && watchedStatus !== undefined && (
|
||||
<EpisodesContext
|
||||
slug={slug}
|
||||
|
@ -127,7 +127,7 @@ export const Player = ({ slug, type }: { slug: string; type: "episode" | "movie"
|
||||
next={next}
|
||||
previous={previous}
|
||||
/>
|
||||
{data && <WatchStatusObserver type={type} slug={data.slug} />}
|
||||
{data && info && <WatchStatusObserver type={type} slug={data.slug} duration={info.length} />}
|
||||
<View
|
||||
{...css({
|
||||
flexGrow: 1,
|
||||
|
@ -28,9 +28,11 @@ import { playAtom, progressAtom } from "./state";
|
||||
export const WatchStatusObserver = ({
|
||||
type,
|
||||
slug,
|
||||
duration,
|
||||
}: {
|
||||
type: "episode" | "movie";
|
||||
slug: string;
|
||||
duration: number;
|
||||
}) => {
|
||||
const account = useAccount();
|
||||
const queryClient = useQueryClient();
|
||||
@ -47,9 +49,10 @@ export const WatchStatusObserver = ({
|
||||
params: {
|
||||
status: WatchStatusV.Watching,
|
||||
watchedTime: Math.round(seconds),
|
||||
percent: Math.round((seconds / duration) * 100),
|
||||
},
|
||||
}),
|
||||
[_mutate, type, slug],
|
||||
[_mutate, type, slug, duration],
|
||||
);
|
||||
const readProgress = useAtomCallback(
|
||||
useCallback((get) => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user