New: Add runtime format option in Settings > UI so users can choose between a mins view and h/m view

This commit is contained in:
nitsua 2020-08-29 11:41:03 -04:00 committed by Qstick
parent 361ffe353d
commit 3548433a10
13 changed files with 82 additions and 30 deletions

View File

@ -118,7 +118,6 @@
}
.links,
.tags,
.rating,
.year,
.runtime {
@ -209,10 +208,13 @@
.certification,
.links,
.tags,
.rating,
.year,
.runtime {
margin-right: 10px;
margin-right: 9px;
}
.details {
font-size: 19px;
}
}

View File

@ -268,7 +268,8 @@ class MovieDetails extends Component {
nextMovie,
onMonitorTogglePress,
onRefreshPress,
onSearchPress
onSearchPress,
movieRuntimeFormat
} = this.props;
const {
@ -426,7 +427,7 @@ class MovieDetails extends Component {
{
!!runtime &&
<span className={styles.runtime}>
{formatRuntime(runtime)}
{formatRuntime(runtime, movieRuntimeFormat)}
</span>
}
@ -465,7 +466,7 @@ class MovieDetails extends Component {
{
!!tags.length &&
<span className={styles.tags}>
<span>
<Popover
anchor={
<Icon
@ -773,7 +774,8 @@ MovieDetails.propTypes = {
onMonitorTogglePress: PropTypes.func.isRequired,
onRefreshPress: PropTypes.func.isRequired,
onSearchPress: PropTypes.func.isRequired,
onGoToMovie: PropTypes.func.isRequired
onGoToMovie: PropTypes.func.isRequired,
movieRuntimeFormat: PropTypes.string.isRequired
};
MovieDetails.defaultProps = {

View File

@ -88,7 +88,8 @@ function createMapStateToProps() {
createCommandsSelector(),
createDimensionsSelector(),
(state) => state.app.isSidebarVisible,
(titleSlug, movieFiles, movieCredits, extraFiles, allMovies, commands, dimensions, isSidebarVisible) => {
(state) => state.settings.ui.item.movieRuntimeFormat,
(titleSlug, movieFiles, movieCredits, extraFiles, allMovies, commands, dimensions, isSidebarVisible, movieRuntimeFormat) => {
const sortedMovies = _.orderBy(allMovies, 'sortTitle');
const movieIndex = _.findIndex(sortedMovies, { titleSlug });
const movie = sortedMovies[movieIndex];
@ -160,7 +161,8 @@ function createMapStateToProps() {
previousMovie,
nextMovie,
isSmallScreen: dimensions.isSmallScreen,
isSidebarVisible
isSidebarVisible,
movieRuntimeFormat
};
}
);

View File

@ -97,7 +97,8 @@ class MovieIndexRow extends Component {
isSelected,
onRefreshMoviePress,
onSearchPress,
onSelectedChange
onSelectedChange,
movieRuntimeFormat
} = this.props;
const {
@ -253,7 +254,7 @@ class MovieIndexRow extends Component {
key={name}
className={styles[name]}
>
{formatRuntime(runtime)}
{formatRuntime(runtime, movieRuntimeFormat)}
</VirtualTableRowCell>
);
}
@ -462,7 +463,8 @@ MovieIndexRow.propTypes = {
onSelectedChange: PropTypes.func.isRequired,
tmdbId: PropTypes.number.isRequired,
imdbId: PropTypes.string,
youTubeTrailerId: PropTypes.string
youTubeTrailerId: PropTypes.string,
movieRuntimeFormat: PropTypes.string.isRequired
};
MovieIndexRow.defaultProps = {

View File

@ -49,7 +49,8 @@ class MovieIndexTable extends Component {
columns,
selectedState,
onSelectedChange,
isMovieEditorActive
isMovieEditorActive,
movieRuntimeFormat
} = this.props;
const movie = items[rowIndex];
@ -68,6 +69,7 @@ class MovieIndexTable extends Component {
isSelected={selectedState[movie.id]}
onSelectedChange={onSelectedChange}
isMovieEditorActive={isMovieEditorActive}
movieRuntimeFormat={movieRuntimeFormat}
/>
</VirtualTableRow>
);
@ -135,7 +137,8 @@ MovieIndexTable.propTypes = {
selectedState: PropTypes.object.isRequired,
onSelectedChange: PropTypes.func.isRequired,
onSelectAllChange: PropTypes.func.isRequired,
isMovieEditorActive: PropTypes.bool.isRequired
isMovieEditorActive: PropTypes.bool.isRequired,
movieRuntimeFormat: PropTypes.string.isRequired
};
export default MovieIndexTable;

View File

@ -8,11 +8,13 @@ function createMapStateToProps() {
(state) => state.app.dimensions,
(state) => state.movieIndex.tableOptions,
(state) => state.movieIndex.columns,
(dimensions, tableOptions, columns) => {
(state) => state.settings.ui.item.movieRuntimeFormat,
(dimensions, tableOptions, columns, movieRuntimeFormat) => {
return {
isSmallScreen: dimensions.isSmallScreen,
showBanners: tableOptions.showBanners,
columns
columns,
movieRuntimeFormat
};
}
);

View File

@ -43,6 +43,11 @@ export const timeFormatOptions = [
{ key: 'HH:mm', value: '17:00/17:30' }
];
export const movieRuntimeFormatOptions = [
{ key: 'hoursMinutes', value: '1h 15m' },
{ key: 'minutes', value: '75 mins' }
];
class UISettings extends Component {
//
@ -111,9 +116,21 @@ class UISettings extends Component {
</FormGroup>
</FieldSet>
<FieldSet
legend={translate('Dates')}
>
<FieldSet legend={translate('Movies')}>
<FormGroup>
<FormLabel>{translate('SettingsRuntimeFormat')}</FormLabel>
<FormInputGroup
type={inputTypes.SELECT}
name="movieRuntimeFormat"
values={movieRuntimeFormatOptions}
onChange={onInputChange}
{...settings.movieRuntimeFormat}
/>
</FormGroup>
</FieldSet>
<FieldSet legend={translate('Dates')}>
<FormGroup>
<FormLabel>{translate('SettingsShortDateFormat')}</FormLabel>
@ -162,9 +179,7 @@ class UISettings extends Component {
</FormGroup>
</FieldSet>
<FieldSet
legend={translate('Style')}
>
<FieldSet legend={translate('Style')}>
<FormGroup>
<FormLabel>{translate('SettingsEnableColorImpairedMode')}</FormLabel>
<FormInputGroup
@ -177,9 +192,7 @@ class UISettings extends Component {
</FormGroup>
</FieldSet>
<FieldSet
legend={translate('Language')}
>
<FieldSet legend={translate('Language')}>
<FormGroup>
<FormLabel>{translate('SettingsUiLanguage')}</FormLabel>
<FormInputGroup

View File

@ -1,13 +1,15 @@
function formatRuntime(minutes) {
function formatRuntime(minutes, format) {
if (!minutes) {
return '0m';
return (format === 'hoursMinutes') ? '0m' : '0 mins';
}
if (format === 'minutes') {
return `${minutes} mins`;
}
const movieHours = Math.floor(minutes / 60);
const movieMinutes = (minutes <= 59) ? minutes : minutes % 60;
const formattedRuntime = `${((movieHours > 0) ? `${movieHours}h ` : '') + movieMinutes}m`;
return formattedRuntime;
return `${((movieHours > 0) ? `${movieHours}h ` : '') + movieMinutes}m`;
}
export default formatRuntime;

View File

@ -5,6 +5,7 @@ using System.Linq;
using NLog;
using NzbDrone.Common.EnsureThat;
using NzbDrone.Common.Http.Proxy;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Configuration.Events;
using NzbDrone.Core.Languages;
using NzbDrone.Core.MediaFiles;
@ -336,6 +337,13 @@ namespace NzbDrone.Core.Configuration
set { SetValue("CalendarWeekColumnHeader", value); }
}
public MovieRuntimeFormatType MovieRuntimeFormat
{
get { return GetValueEnum("MovieRuntimeFormat", MovieRuntimeFormatType.HoursMinutes); }
set { SetValue("MovieRuntimeFormat", value); }
}
public string ShortDateFormat
{
get { return GetValue("ShortDateFormat", "MMM D YYYY"); }

View File

@ -1,5 +1,6 @@
using System.Collections.Generic;
using NzbDrone.Common.Http.Proxy;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
using NzbDrone.Core.Security;
@ -68,6 +69,7 @@ namespace NzbDrone.Core.Configuration
//UI
int FirstDayOfWeek { get; set; }
string CalendarWeekColumnHeader { get; set; }
MovieRuntimeFormatType MovieRuntimeFormat { get; set; }
string ShortDateFormat { get; set; }
string LongDateFormat { get; set; }

View File

@ -0,0 +1,8 @@
namespace NzbDrone.Core.Configuration
{
public enum MovieRuntimeFormatType
{
HoursMinutes,
Minutes
}
}

View File

@ -523,6 +523,7 @@
"SettingsRemotePathMappingLocalPathHelpText": "Path that Radarr should use to access the remote path locally",
"SettingsRemotePathMappingRemotePath": "Remote Path",
"SettingsRemotePathMappingRemotePathHelpText": "Root path to the directory that the Download Client accesses",
"SettingsRuntimeFormat": "Runtime Format",
"SettingsShortDateFormat": "Short Date Format",
"SettingsShowRelativeDates": "Show Relative Dates",
"SettingsShowRelativeDatesHelpText": "Show relative (Today/Yesterday/etc) or absolute dates",

View File

@ -9,6 +9,9 @@ namespace Radarr.Api.V3.Config
public int FirstDayOfWeek { get; set; }
public string CalendarWeekColumnHeader { get; set; }
// Movies
public MovieRuntimeFormatType MovieRuntimeFormat { get; set; }
//Dates
public string ShortDateFormat { get; set; }
public string LongDateFormat { get; set; }
@ -28,6 +31,8 @@ namespace Radarr.Api.V3.Config
FirstDayOfWeek = model.FirstDayOfWeek,
CalendarWeekColumnHeader = model.CalendarWeekColumnHeader,
MovieRuntimeFormat = model.MovieRuntimeFormat,
ShortDateFormat = model.ShortDateFormat,
LongDateFormat = model.LongDateFormat,
TimeFormat = model.TimeFormat,