1
0
mirror of https://github.com/Radarr/Radarr.git synced 2024-11-19 17:32:38 +01:00

Fixed: Improve sorting movies by release dates

This commit is contained in:
Bogdan 2024-08-23 03:21:19 +03:00
parent bf84471509
commit df77474314
15 changed files with 99 additions and 34 deletions

View File

@ -106,7 +106,7 @@ function MovieIndexSortMenu(props: MovieIndexSortMenuProps) {
sortDirection={sortDirection}
onPress={onSortSelect}
>
{translate('ReleaseDates')}
{translate('ReleaseDate')}
</SortMenuItem>
<SortMenuItem

View File

@ -75,6 +75,7 @@ function MovieIndexPoster(props: MovieIndexPosterProps) {
inCinemas,
physicalRelease,
digitalRelease,
releaseDate,
path,
movieFile,
ratings,
@ -142,20 +143,6 @@ function MovieIndexPoster(props: MovieIndexPosterProps) {
height: `${posterHeight}px`,
};
let releaseDate = '';
let releaseDateType = '';
if (physicalRelease && digitalRelease) {
releaseDate =
physicalRelease < digitalRelease ? physicalRelease : digitalRelease;
releaseDateType = physicalRelease < digitalRelease ? 'Released' : 'Digital';
} else if (physicalRelease && !digitalRelease) {
releaseDate = physicalRelease;
releaseDateType = 'Released';
} else if (digitalRelease && !physicalRelease) {
releaseDate = digitalRelease;
releaseDateType = 'Digital';
}
return (
<div className={styles.content}>
<div className={styles.posterContainer} title={title}>
@ -262,10 +249,8 @@ function MovieIndexPoster(props: MovieIndexPosterProps) {
) : null}
{showReleaseDate && releaseDate ? (
<div className={styles.title}>
<Icon
name={releaseDateType === 'Digital' ? icons.MOVIE_FILE : icons.DISC}
/>{' '}
<div className={styles.title} title={translate('ReleaseDate')}>
<Icon name={icons.CALENDAR} />{' '}
{getRelativeDate(releaseDate, shortDateFormat, showRelativeDates, {
timeFormat,
timeForToday: false,
@ -314,6 +299,7 @@ function MovieIndexPoster(props: MovieIndexPosterProps) {
inCinemas={inCinemas}
physicalRelease={physicalRelease}
digitalRelease={digitalRelease}
releaseDate={releaseDate}
ratings={ratings}
sizeOnDisk={sizeOnDisk}
sortKey={sortKey}

View File

@ -23,6 +23,7 @@ interface MovieIndexPosterInfoProps {
inCinemas?: string;
digitalRelease?: string;
physicalRelease?: string;
releaseDate?: string;
path: string;
ratings: Ratings;
certification: string;
@ -53,6 +54,7 @@ function MovieIndexPosterInfo(props: MovieIndexPosterInfoProps) {
inCinemas,
digitalRelease,
physicalRelease,
releaseDate,
path,
ratings,
certification,
@ -152,7 +154,7 @@ function MovieIndexPosterInfo(props: MovieIndexPosterInfoProps) {
);
return (
<div className={styles.info}>
<div className={styles.info} title={translate('DigitalRelease')}>
<Icon name={icons.MOVIE_FILE} /> {digitalReleaseDate}
</div>
);
@ -170,12 +172,24 @@ function MovieIndexPosterInfo(props: MovieIndexPosterInfoProps) {
);
return (
<div className={styles.info}>
<div className={styles.info} title={translate('PhysicalRelease')}>
<Icon name={icons.DISC} /> {physicalReleaseDate}
</div>
);
}
if (sortKey === 'releaseDate' && releaseDate && !showReleaseDate) {
return (
<div className={styles.info} title={translate('ReleaseDate')}>
<Icon name={icons.CALENDAR} />{' '}
{getRelativeDate(releaseDate, shortDateFormat, showRelativeDates, {
timeFormat,
timeForToday: false,
})}
</div>
);
}
if (!showTmdbRating && sortKey === 'tmdbRating' && !!ratings.tmdb) {
return (
<div className={styles.info}>

View File

@ -218,6 +218,7 @@ export default function MovieIndexPosters(props: MovieIndexPostersProps) {
break;
case 'digitalRelease':
case 'physicalRelease':
case 'releaseDate':
if (!showReleaseDate) {
heights.push(19);
}

View File

@ -42,6 +42,7 @@
.inCinemas,
.physicalRelease,
.digitalRelease,
.releaseDate,
.genres {
composes: cell;

View File

@ -20,6 +20,7 @@ interface CssExports {
'physicalRelease': string;
'popularity': string;
'qualityProfileId': string;
'releaseDate': string;
'releaseGroups': string;
'rottenTomatoesRating': string;
'runtime': string;

View File

@ -66,6 +66,7 @@ function MovieIndexRow(props: MovieIndexRowProps) {
inCinemas,
digitalRelease,
physicalRelease,
releaseDate,
runtime,
minimumAvailability,
path,
@ -278,6 +279,19 @@ function MovieIndexRow(props: MovieIndexRowProps) {
);
}
if (name === 'releaseDate') {
return (
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore ts(2739)
<RelativeDateCellConnector
key={name}
className={styles[name]}
date={releaseDate}
component={VirtualTableRowCell}
/>
);
}
if (name === 'runtime') {
return (
<VirtualTableRowCell key={name} className={styles[name]}>

View File

@ -35,6 +35,7 @@
.inCinemas,
.physicalRelease,
.digitalRelease,
.releaseDate,
.genres {
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';

View File

@ -17,6 +17,7 @@ interface CssExports {
'physicalRelease': string;
'popularity': string;
'qualityProfileId': string;
'releaseDate': string;
'releaseGroups': string;
'rottenTomatoesRating': string;
'runtime': string;

View File

@ -42,16 +42,17 @@ interface Movie extends ModelBase {
status: MovieStatus;
title: string;
titleSlug: string;
originalTitle: string;
originalLanguage: Language;
collection: Collection;
studio: string;
qualityProfileId: number;
added: string;
year: number;
inCinemas: string;
physicalRelease: string;
originalLanguage: Language;
originalTitle: string;
digitalRelease: string;
inCinemas?: string;
physicalRelease?: string;
digitalRelease?: string;
releaseDate?: string;
runtime: number;
minimumAvailability: string;
path: string;

View File

@ -258,8 +258,10 @@ export const sortPredicates = {
},
inCinemas: function(item, direction) {
if (item.inCinemas) {
return moment(item.inCinemas).unix();
const { inCinemas } = item;
if (inCinemas) {
return moment(inCinemas).unix();
}
if (direction === sortDirections.DESCENDING) {
@ -270,8 +272,10 @@ export const sortPredicates = {
},
physicalRelease: function(item, direction) {
if (item.physicalRelease) {
return moment(item.physicalRelease).unix();
const { physicalRelease } = item;
if (physicalRelease) {
return moment(physicalRelease).unix();
}
if (direction === sortDirections.DESCENDING) {
@ -282,8 +286,10 @@ export const sortPredicates = {
},
digitalRelease: function(item, direction) {
if (item.digitalRelease) {
return moment(item.digitalRelease).unix();
const { digitalRelease } = item;
if (digitalRelease) {
return moment(digitalRelease).unix();
}
if (direction === sortDirections.DESCENDING) {
@ -294,8 +300,7 @@ export const sortPredicates = {
},
releaseDate: function(item, direction) {
const { inCinemas, digitalRelease, physicalRelease } = item;
const releaseDate = digitalRelease || physicalRelease || inCinemas;
const { releaseDate } = item;
if (releaseDate) {
return moment(releaseDate).unix();

View File

@ -142,6 +142,12 @@ export const defaultState = {
isSortable: true,
isVisible: false
},
{
name: 'releaseDate',
label: () => translate('ReleaseDate'),
isSortable: true,
isVisible: false
},
{
name: 'runtime',
label: () => translate('Runtime'),
@ -433,6 +439,12 @@ export const defaultState = {
type: filterBuilderTypes.DATE,
valueType: filterBuilderValueTypes.DATE
},
{
name: 'releaseDate',
label: () => translate('ReleaseDate'),
type: filterBuilderTypes.DATE,
valueType: filterBuilderValueTypes.DATE
},
{
name: 'runtime',
label: () => translate('Runtime'),

View File

@ -1380,6 +1380,7 @@
"RelativePath": "Relative Path",
"Release": "Release",
"ReleaseBranchCheckOfficialBranchMessage": "Branch {0} is not a valid {appName} release branch, you will not receive updates",
"ReleaseDate": "Release Date",
"ReleaseDates": "Release Dates",
"ReleaseGroup": "Release Group",
"ReleaseGroupFootNote": "Optionally control truncation to a maximum number of bytes including ellipsis (`...`). Truncating from the end (e.g. `{Release Group:30}`) or the beginning (e.g. `{Release Group:-30}`) are both supported.`).",

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.MediaFiles;
@ -117,6 +118,30 @@ public bool IsAvailable(int delay = 0)
return DateTime.UtcNow >= minimumAvailabilityDate.AddDays(delay);
}
public DateTime? GetReleaseDate()
{
if (MinimumAvailability is MovieStatusType.TBA or MovieStatusType.Announced)
{
return new[] { MovieMetadata.Value.InCinemas, MovieMetadata.Value.DigitalRelease, MovieMetadata.Value.PhysicalRelease }
.Where(x => x.HasValue)
.Min();
}
if (MinimumAvailability == MovieStatusType.InCinemas && MovieMetadata.Value.InCinemas.HasValue)
{
return MovieMetadata.Value.InCinemas.Value;
}
if (MovieMetadata.Value.DigitalRelease.HasValue || MovieMetadata.Value.PhysicalRelease.HasValue)
{
return new[] { MovieMetadata.Value.DigitalRelease, MovieMetadata.Value.PhysicalRelease }
.Where(x => x.HasValue)
.Min();
}
return MovieMetadata.Value.InCinemas?.AddDays(90);
}
public override string ToString()
{
return string.Format("[{1} ({2})][{0}, {3}]", MovieMetadata.Value.ImdbId, MovieMetadata.Value.Title.NullSafe(), MovieMetadata.Value.Year.NullSafe(), MovieMetadata.Value.TmdbId);

View File

@ -42,6 +42,7 @@ public MovieResource()
public DateTime? InCinemas { get; set; }
public DateTime? PhysicalRelease { get; set; }
public DateTime? DigitalRelease { get; set; }
public DateTime? ReleaseDate { get; set; }
public string PhysicalReleaseNote { get; set; }
public List<MediaCover> Images { get; set; }
public string Website { get; set; }
@ -122,6 +123,7 @@ public static MovieResource ToResource(this Movie model, int availDelay, MovieTr
InCinemas = model.MovieMetadata.Value.InCinemas,
PhysicalRelease = model.MovieMetadata.Value.PhysicalRelease,
DigitalRelease = model.MovieMetadata.Value.DigitalRelease,
ReleaseDate = model.GetReleaseDate(),
Status = model.MovieMetadata.Value.Status,
Overview = translatedOverview,