mirror of
https://github.com/Radarr/Radarr
synced 2026-01-25 08:53:02 +01:00
Merge a8dfbdd17e into 89110c2cc8
This commit is contained in:
commit
3347df618a
8 changed files with 177 additions and 0 deletions
|
|
@ -88,9 +88,32 @@
|
|||
.sizeOnDisk {
|
||||
composes: cell;
|
||||
|
||||
justify-content: flex-end;
|
||||
|
||||
flex: 0 0 120px;
|
||||
}
|
||||
|
||||
.gigabytesPerHour {
|
||||
composes: cell;
|
||||
|
||||
justify-content: flex-end;
|
||||
|
||||
flex: 0 0 100px;
|
||||
}
|
||||
|
||||
.audioCodec,
|
||||
.videoCodec {
|
||||
composes: cell;
|
||||
|
||||
flex: 0 0 110px;
|
||||
}
|
||||
|
||||
.resolution {
|
||||
composes: cell;
|
||||
|
||||
flex: 0 0 100px;
|
||||
}
|
||||
|
||||
.imdbRating,
|
||||
.tmdbRating,
|
||||
.rottenTomatoesRating,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
interface CssExports {
|
||||
'actions': string;
|
||||
'added': string;
|
||||
'audioCodec': string;
|
||||
'cell': string;
|
||||
'certification': string;
|
||||
'checkInput': string;
|
||||
|
|
@ -10,6 +11,7 @@ interface CssExports {
|
|||
'digitalRelease': string;
|
||||
'externalLinks': string;
|
||||
'genres': string;
|
||||
'gigabytesPerHour': string;
|
||||
'imdbRating': string;
|
||||
'inCinemas': string;
|
||||
'keywords': string;
|
||||
|
|
@ -23,6 +25,7 @@ interface CssExports {
|
|||
'qualityProfileId': string;
|
||||
'releaseDate': string;
|
||||
'releaseGroups': string;
|
||||
'resolution': string;
|
||||
'rottenTomatoesRating': string;
|
||||
'runtime': string;
|
||||
'sizeOnDisk': string;
|
||||
|
|
@ -32,6 +35,7 @@ interface CssExports {
|
|||
'tags': string;
|
||||
'tmdbRating': string;
|
||||
'traktRating': string;
|
||||
'videoCodec': string;
|
||||
'year': string;
|
||||
}
|
||||
export const cssExports: CssExports;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
|
|||
import { SelectStateInputProps } from 'typings/props';
|
||||
import formatRuntime from 'Utilities/Date/formatRuntime';
|
||||
import formatBytes from 'Utilities/Number/formatBytes';
|
||||
import parseRuntimeToHours from 'Utilities/Number/parseRuntimeToHours';
|
||||
import firstCharToUpper from 'Utilities/String/firstCharToUpper';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import MovieIndexProgressBar from '../ProgressBar/MovieIndexProgressBar';
|
||||
|
|
@ -330,6 +331,44 @@ function MovieIndexRow(props: MovieIndexRowProps) {
|
|||
);
|
||||
}
|
||||
|
||||
if (name === 'gigabytesPerHour') {
|
||||
const runtimeHours = parseRuntimeToHours(
|
||||
movieFile?.mediaInfo?.runTime
|
||||
);
|
||||
const gigabytesPerHour =
|
||||
runtimeHours > 0 ? sizeOnDisk / 1073741824 / runtimeHours : 0;
|
||||
|
||||
return (
|
||||
<VirtualTableRowCell key={name} className={styles[name]}>
|
||||
{gigabytesPerHour.toFixed(2)}
|
||||
</VirtualTableRowCell>
|
||||
);
|
||||
}
|
||||
|
||||
if (name === 'audioCodec') {
|
||||
return (
|
||||
<VirtualTableRowCell key={name} className={styles[name]}>
|
||||
{movieFile?.mediaInfo?.audioCodec ?? ''}
|
||||
</VirtualTableRowCell>
|
||||
);
|
||||
}
|
||||
|
||||
if (name === 'videoCodec') {
|
||||
return (
|
||||
<VirtualTableRowCell key={name} className={styles[name]}>
|
||||
{movieFile?.mediaInfo?.videoCodec ?? ''}
|
||||
</VirtualTableRowCell>
|
||||
);
|
||||
}
|
||||
|
||||
if (name === 'resolution') {
|
||||
return (
|
||||
<VirtualTableRowCell key={name} className={styles[name]}>
|
||||
{movieFile?.mediaInfo?.resolution ?? ''}
|
||||
</VirtualTableRowCell>
|
||||
);
|
||||
}
|
||||
|
||||
if (name === 'genres') {
|
||||
const joinedGenres = genres.join(', ');
|
||||
|
||||
|
|
|
|||
|
|
@ -78,9 +78,32 @@
|
|||
.sizeOnDisk {
|
||||
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
|
||||
|
||||
justify-content: flex-end;
|
||||
|
||||
flex: 0 0 120px;
|
||||
}
|
||||
|
||||
.gigabytesPerHour {
|
||||
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
|
||||
|
||||
justify-content: flex-end;
|
||||
|
||||
flex: 0 0 100px;
|
||||
}
|
||||
|
||||
.audioCodec,
|
||||
.videoCodec {
|
||||
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
|
||||
|
||||
flex: 0 0 110px;
|
||||
}
|
||||
|
||||
.resolution {
|
||||
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
|
||||
|
||||
flex: 0 0 100px;
|
||||
}
|
||||
|
||||
.imdbRating,
|
||||
.tmdbRating,
|
||||
.rottenTomatoesRating,
|
||||
|
|
|
|||
|
|
@ -3,10 +3,12 @@
|
|||
interface CssExports {
|
||||
'actions': string;
|
||||
'added': string;
|
||||
'audioCodec': string;
|
||||
'certification': string;
|
||||
'collection': string;
|
||||
'digitalRelease': string;
|
||||
'genres': string;
|
||||
'gigabytesPerHour': string;
|
||||
'imdbRating': string;
|
||||
'inCinemas': string;
|
||||
'keywords': string;
|
||||
|
|
@ -20,6 +22,7 @@ interface CssExports {
|
|||
'qualityProfileId': string;
|
||||
'releaseDate': string;
|
||||
'releaseGroups': string;
|
||||
'resolution': string;
|
||||
'rottenTomatoesRating': string;
|
||||
'runtime': string;
|
||||
'sizeOnDisk': string;
|
||||
|
|
@ -29,6 +32,7 @@ interface CssExports {
|
|||
'tags': string;
|
||||
'tmdbRating': string;
|
||||
'traktRating': string;
|
||||
'videoCodec': string;
|
||||
'year': string;
|
||||
}
|
||||
export const cssExports: CssExports;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { createAction } from 'redux-actions';
|
||||
import { filterBuilderTypes, filterBuilderValueTypes, sortDirections } from 'Helpers/Props';
|
||||
import sortByProp from 'Utilities/Array/sortByProp';
|
||||
import parseRuntimeToHours from 'Utilities/Number/parseRuntimeToHours';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import createHandleActions from './Creators/createHandleActions';
|
||||
import createSetClientSideCollectionFilterReducer from './Creators/Reducers/createSetClientSideCollectionFilterReducer';
|
||||
|
|
@ -175,6 +176,30 @@ export const defaultState = {
|
|||
isSortable: true,
|
||||
isVisible: false
|
||||
},
|
||||
{
|
||||
name: 'gigabytesPerHour',
|
||||
label: () => translate('GigabytesPerHour'),
|
||||
isSortable: true,
|
||||
isVisible: false
|
||||
},
|
||||
{
|
||||
name: 'audioCodec',
|
||||
label: () => translate('AudioCodec'),
|
||||
isSortable: true,
|
||||
isVisible: false
|
||||
},
|
||||
{
|
||||
name: 'videoCodec',
|
||||
label: () => translate('VideoCodec'),
|
||||
isSortable: true,
|
||||
isVisible: false
|
||||
},
|
||||
{
|
||||
name: 'resolution',
|
||||
label: () => translate('Resolution'),
|
||||
isSortable: true,
|
||||
isVisible: false
|
||||
},
|
||||
{
|
||||
name: 'genres',
|
||||
label: () => translate('Genres'),
|
||||
|
|
@ -295,6 +320,36 @@ export const defaultState = {
|
|||
|
||||
traktRating: function({ ratings = {} }) {
|
||||
return ratings.trakt ? ratings.trakt.value : 0;
|
||||
},
|
||||
|
||||
gigabytesPerHour: function(item) {
|
||||
const { statistics = {}, movieFile } = item;
|
||||
const { sizeOnDisk = 0 } = statistics;
|
||||
const runtimeHours = parseRuntimeToHours(movieFile?.mediaInfo?.runTime);
|
||||
|
||||
if (runtimeHours === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return sizeOnDisk / runtimeHours;
|
||||
},
|
||||
|
||||
audioCodec: function(item) {
|
||||
const { movieFile } = item;
|
||||
|
||||
return movieFile?.mediaInfo?.audioCodec ?? '';
|
||||
},
|
||||
|
||||
videoCodec: function(item) {
|
||||
const { movieFile } = item;
|
||||
|
||||
return movieFile?.mediaInfo?.videoCodec ?? '';
|
||||
},
|
||||
|
||||
resolution: function(item) {
|
||||
const { movieFile } = item;
|
||||
|
||||
return movieFile?.mediaInfo?.resolution ?? '';
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
|||
26
frontend/src/Utilities/Number/parseRuntimeToHours.ts
Normal file
26
frontend/src/Utilities/Number/parseRuntimeToHours.ts
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// Parses a runtime string in "H:MM:SS" or "M:SS" format to decimal hours
|
||||
function parseRuntimeToHours(runTime: string | undefined): number {
|
||||
if (!runTime) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const parts = runTime.split(':').map(Number);
|
||||
|
||||
if (parts.some(isNaN)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (parts.length === 3) {
|
||||
// H:MM:SS format
|
||||
return parts[0] + parts[1] / 60 + parts[2] / 3600;
|
||||
}
|
||||
|
||||
if (parts.length === 2) {
|
||||
// M:SS format
|
||||
return parts[0] / 60 + parts[1] / 3600;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
export default parseRuntimeToHours;
|
||||
|
|
@ -95,6 +95,7 @@
|
|||
"ApplyTagsHelpTextRemove": "Remove: Remove the entered tags",
|
||||
"ApplyTagsHelpTextReplace": "Replace: Replace the tags with the entered tags (enter no tags to clear all tags)",
|
||||
"AptUpdater": "Use apt to install the update",
|
||||
"AudioCodec": "Audio Codec",
|
||||
"AudioInfo": "Audio Info",
|
||||
"AudioLanguages": "Audio Languages",
|
||||
"AuthBasic": "Basic (Browser Popup)",
|
||||
|
|
@ -725,6 +726,7 @@
|
|||
"From": "from",
|
||||
"FullColorEvents": "Full Color Events",
|
||||
"FullColorEventsHelpText": "Altered style to color the entire event with the status color, instead of just the left edge. Does not apply to Agenda",
|
||||
"GigabytesPerHour": "Gigabytes Per Hour",
|
||||
"General": "General",
|
||||
"GeneralSettings": "General Settings",
|
||||
"GeneralSettingsLoadError": "Unable to load General settings",
|
||||
|
|
@ -1683,6 +1685,7 @@
|
|||
"ResetQualityDefinitions": "Reset Quality Definitions",
|
||||
"ResetQualityDefinitionsMessageText": "Are you sure you want to reset quality definitions?",
|
||||
"ResetTitles": "Reset Titles",
|
||||
"Resolution": "Resolution",
|
||||
"Restart": "Restart",
|
||||
"RestartLater": "I'll restart later",
|
||||
"RestartNow": "Restart Now",
|
||||
|
|
|
|||
Loading…
Reference in a new issue