mirror of
https://github.com/Sonarr/Sonarr.git
synced 2026-04-17 21:26:13 -04:00
Compare commits
5 Commits
v4.0.4.169
...
v4.0.4.169
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
66940b283b | ||
|
|
2a662afaef | ||
|
|
62a9c2519b | ||
|
|
ca372bee25 | ||
|
|
0904a0737e |
@@ -24,7 +24,11 @@ function TimeleftCell(props) {
|
||||
} = props;
|
||||
|
||||
if (status === 'delay') {
|
||||
const date = getRelativeDate(estimatedCompletionTime, shortDateFormat, showRelativeDates);
|
||||
const date = getRelativeDate({
|
||||
date: estimatedCompletionTime,
|
||||
shortDateFormat,
|
||||
showRelativeDates
|
||||
});
|
||||
const time = formatTime(estimatedCompletionTime, timeFormat, { includeMinuteZero: true });
|
||||
|
||||
return (
|
||||
@@ -40,7 +44,11 @@ function TimeleftCell(props) {
|
||||
}
|
||||
|
||||
if (status === 'downloadClientUnavailable') {
|
||||
const date = getRelativeDate(estimatedCompletionTime, shortDateFormat, showRelativeDates);
|
||||
const date = getRelativeDate({
|
||||
date: estimatedCompletionTime,
|
||||
shortDateFormat,
|
||||
showRelativeDates
|
||||
});
|
||||
const time = formatTime(estimatedCompletionTime, timeFormat, { includeMinuteZero: true });
|
||||
|
||||
return (
|
||||
|
||||
@@ -28,7 +28,7 @@ class DayOfWeek extends Component {
|
||||
if (view === calendarViews.WEEK) {
|
||||
formatedDate = momentDate.format(calendarWeekColumnHeader);
|
||||
} else if (view === calendarViews.FORECAST) {
|
||||
formatedDate = getRelativeDate(date, shortDateFormat, showRelativeDates);
|
||||
formatedDate = getRelativeDate({ date, shortDateFormat, showRelativeDates });
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -40,7 +40,7 @@ class RelativeDateCell extends PureComponent {
|
||||
title={formatDateTime(date, longDateFormat, timeFormat, { includeSeconds, includeRelativeDay: !showRelativeDates })}
|
||||
{...otherProps}
|
||||
>
|
||||
{getRelativeDate(date, shortDateFormat, showRelativeDates, { timeFormat, includeSeconds, includeTime, timeForToday: true })}
|
||||
{getRelativeDate({ date, shortDateFormat, showRelativeDates, timeFormat, includeSeconds, includeTime, timeForToday: true })}
|
||||
</Component>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -138,7 +138,10 @@ function getInfoRowProps(
|
||||
}),
|
||||
iconName: icons.CALENDAR,
|
||||
label:
|
||||
getRelativeDate(previousAiring, shortDateFormat, showRelativeDates, {
|
||||
getRelativeDate({
|
||||
date: previousAiring,
|
||||
shortDateFormat,
|
||||
showRelativeDates,
|
||||
timeFormat,
|
||||
timeForToday: true,
|
||||
}) ?? '',
|
||||
@@ -156,7 +159,10 @@ function getInfoRowProps(
|
||||
}),
|
||||
iconName: icons.ADD,
|
||||
label:
|
||||
getRelativeDate(added, shortDateFormat, showRelativeDates, {
|
||||
getRelativeDate({
|
||||
date: added,
|
||||
shortDateFormat,
|
||||
showRelativeDates,
|
||||
timeFormat,
|
||||
timeForToday: true,
|
||||
}) ?? '',
|
||||
@@ -232,15 +238,13 @@ function SeriesIndexOverviewInfo(props: SeriesIndexOverviewInfoProps) {
|
||||
<SeriesIndexOverviewInfoRow
|
||||
title={formatDateTime(nextAiring, longDateFormat, timeFormat)}
|
||||
iconName={icons.SCHEDULED}
|
||||
label={getRelativeDate(
|
||||
nextAiring,
|
||||
label={getRelativeDate({
|
||||
date: nextAiring,
|
||||
shortDateFormat,
|
||||
showRelativeDates,
|
||||
{
|
||||
timeFormat,
|
||||
timeForToday: true,
|
||||
}
|
||||
)}
|
||||
timeFormat,
|
||||
timeForToday: true,
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
@@ -217,7 +217,10 @@ function SeriesIndexPoster(props: SeriesIndexPosterProps) {
|
||||
timeFormat
|
||||
)}`}
|
||||
>
|
||||
{getRelativeDate(nextAiring, shortDateFormat, showRelativeDates, {
|
||||
{getRelativeDate({
|
||||
date: nextAiring,
|
||||
shortDateFormat,
|
||||
showRelativeDates,
|
||||
timeFormat,
|
||||
timeForToday: true,
|
||||
})}
|
||||
|
||||
@@ -80,7 +80,10 @@ function SeriesIndexPosterInfo(props: SeriesIndexPosterInfoProps) {
|
||||
timeFormat
|
||||
)}`}
|
||||
>
|
||||
{getRelativeDate(previousAiring, shortDateFormat, showRelativeDates, {
|
||||
{getRelativeDate({
|
||||
date: previousAiring,
|
||||
shortDateFormat,
|
||||
showRelativeDates,
|
||||
timeFormat,
|
||||
timeForToday: true,
|
||||
})}
|
||||
@@ -89,15 +92,13 @@ function SeriesIndexPosterInfo(props: SeriesIndexPosterInfoProps) {
|
||||
}
|
||||
|
||||
if (sortKey === 'added' && added) {
|
||||
const addedDate = getRelativeDate(
|
||||
added,
|
||||
const addedDate = getRelativeDate({
|
||||
date: added,
|
||||
shortDateFormat,
|
||||
showRelativeDates,
|
||||
{
|
||||
timeFormat,
|
||||
timeForToday: false,
|
||||
}
|
||||
);
|
||||
timeFormat,
|
||||
timeForToday: false,
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
import moment from 'moment';
|
||||
import formatTime from 'Utilities/Date/formatTime';
|
||||
import isInNextWeek from 'Utilities/Date/isInNextWeek';
|
||||
import isToday from 'Utilities/Date/isToday';
|
||||
import isTomorrow from 'Utilities/Date/isTomorrow';
|
||||
import isYesterday from 'Utilities/Date/isYesterday';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import formatDateTime from './formatDateTime';
|
||||
|
||||
function getRelativeDate(date, shortDateFormat, showRelativeDates, { timeFormat, includeSeconds = false, timeForToday = false, includeTime = false } = {}) {
|
||||
if (!date) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const isTodayDate = isToday(date);
|
||||
const time = formatTime(date, timeFormat, { includeMinuteZero: true, includeSeconds });
|
||||
|
||||
if (isTodayDate && timeForToday && timeFormat) {
|
||||
return time;
|
||||
}
|
||||
|
||||
if (!showRelativeDates) {
|
||||
return moment(date).format(shortDateFormat);
|
||||
}
|
||||
|
||||
if (isYesterday(date)) {
|
||||
return includeTime ? translate('YesterdayAt', { time } ): translate('Yesterday');
|
||||
}
|
||||
|
||||
if (isTodayDate) {
|
||||
return includeTime ? translate('TodayAt', { time } ): translate('Today');
|
||||
}
|
||||
|
||||
if (isTomorrow(date)) {
|
||||
return includeTime ? translate('TomorrowAt', { time } ): translate('Tomorrow');
|
||||
}
|
||||
|
||||
if (isInNextWeek(date)) {
|
||||
const day = moment(date).format('dddd');
|
||||
|
||||
return includeTime ? translate('DayOfWeekAt', { day, time }) : day;
|
||||
}
|
||||
|
||||
return includeTime ?
|
||||
formatDateTime(date, shortDateFormat, timeFormat, { includeSeconds }) :
|
||||
moment(date).format(shortDateFormat);
|
||||
}
|
||||
|
||||
export default getRelativeDate;
|
||||
82
frontend/src/Utilities/Date/getRelativeDate.tsx
Normal file
82
frontend/src/Utilities/Date/getRelativeDate.tsx
Normal file
@@ -0,0 +1,82 @@
|
||||
import moment from 'moment';
|
||||
import formatTime from 'Utilities/Date/formatTime';
|
||||
import isInNextWeek from 'Utilities/Date/isInNextWeek';
|
||||
import isToday from 'Utilities/Date/isToday';
|
||||
import isTomorrow from 'Utilities/Date/isTomorrow';
|
||||
import isYesterday from 'Utilities/Date/isYesterday';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import formatDateTime from './formatDateTime';
|
||||
|
||||
interface GetRelativeDateOptions {
|
||||
date?: string;
|
||||
shortDateFormat: string;
|
||||
showRelativeDates: boolean;
|
||||
timeFormat?: string;
|
||||
includeSeconds?: boolean;
|
||||
timeForToday?: boolean;
|
||||
includeTime?: boolean;
|
||||
}
|
||||
|
||||
function getRelativeDate({
|
||||
date,
|
||||
shortDateFormat,
|
||||
showRelativeDates,
|
||||
timeFormat,
|
||||
includeSeconds = false,
|
||||
timeForToday = false,
|
||||
includeTime = false,
|
||||
}: GetRelativeDateOptions) {
|
||||
if (!date) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ((includeTime || timeForToday) && !timeFormat) {
|
||||
throw new Error(
|
||||
"getRelativeDate: 'timeFormat' is required when 'includeTime' or 'timeForToday' is true"
|
||||
);
|
||||
}
|
||||
|
||||
const isTodayDate = isToday(date);
|
||||
const time = timeFormat
|
||||
? formatTime(date, timeFormat, {
|
||||
includeMinuteZero: true,
|
||||
includeSeconds,
|
||||
})
|
||||
: '';
|
||||
|
||||
if (isTodayDate && timeForToday) {
|
||||
return time;
|
||||
}
|
||||
|
||||
if (!showRelativeDates) {
|
||||
return moment(date).format(shortDateFormat);
|
||||
}
|
||||
|
||||
if (isYesterday(date)) {
|
||||
return includeTime
|
||||
? translate('YesterdayAt', { time })
|
||||
: translate('Yesterday');
|
||||
}
|
||||
|
||||
if (isTodayDate) {
|
||||
return includeTime ? translate('TodayAt', { time }) : translate('Today');
|
||||
}
|
||||
|
||||
if (isTomorrow(date)) {
|
||||
return includeTime
|
||||
? translate('TomorrowAt', { time })
|
||||
: translate('Tomorrow');
|
||||
}
|
||||
|
||||
if (isInNextWeek(date)) {
|
||||
const day = moment(date).format('dddd');
|
||||
|
||||
return includeTime ? translate('DayOfWeekAt', { day, time }) : day;
|
||||
}
|
||||
|
||||
return includeTime
|
||||
? formatDateTime(date, shortDateFormat, timeFormat, { includeSeconds })
|
||||
: moment(date).format(shortDateFormat);
|
||||
}
|
||||
|
||||
export default getRelativeDate;
|
||||
@@ -2074,5 +2074,9 @@
|
||||
"IndexerSettingsMultiLanguageReleaseHelpText": "¿Qué idiomas están normalmente en un lanzamiento múltiple en este indexador?",
|
||||
"DownloadClientQbittorrentTorrentStateMissingFiles": "qBittorrent está reportando archivos faltantes",
|
||||
"BlocklistFilterHasNoItems": "El filtro de lista de bloqueo seleccionado no contiene elementos",
|
||||
"HasUnmonitoredSeason": "Tiene temporada sin monitorizar"
|
||||
"HasUnmonitoredSeason": "Tiene temporada sin monitorizar",
|
||||
"TomorrowAt": "Mañana a las {time}",
|
||||
"YesterdayAt": "Ayer a las {time}",
|
||||
"TodayAt": "Hoy a las {time}",
|
||||
"DayOfWeekAt": "{day} a las {time}"
|
||||
}
|
||||
|
||||
@@ -2073,5 +2073,10 @@
|
||||
"AutoTaggingSpecificationTag": "Etiqueta",
|
||||
"IndexerSettingsMultiLanguageRelease": "Multi Idiomas",
|
||||
"DownloadClientQbittorrentTorrentStateMissingFiles": "qBittorrent está relatando arquivos perdidos",
|
||||
"BlocklistFilterHasNoItems": "O filtro selecionado para a lista de bloqueio não contém itens"
|
||||
"BlocklistFilterHasNoItems": "O filtro selecionado para a lista de bloqueio não contém itens",
|
||||
"DayOfWeekAt": "{day} às {time}",
|
||||
"TodayAt": "Hoje às {time}",
|
||||
"TomorrowAt": "Amanhã às {time}",
|
||||
"HasUnmonitoredSeason": "Tem Temporada Não Monitorada",
|
||||
"YesterdayAt": "Ontem às {time}"
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@
|
||||
"CountIndexersSelected": "已选择 {count} 个索引器",
|
||||
"CurrentlyInstalled": "已安装",
|
||||
"CustomFormats": "自定义命名格式",
|
||||
"CutoffUnmet": "未达截止条件",
|
||||
"CutoffUnmet": "未达设定标准",
|
||||
"Date": "日期",
|
||||
"DeleteBackup": "删除备份",
|
||||
"DeleteCustomFormat": "删除自定义命名格式",
|
||||
@@ -293,7 +293,7 @@
|
||||
"RootFolderMultipleMissingHealthCheckMessage": "多个根目录缺失:{rootFolderPaths}",
|
||||
"SkipRedownloadHelpText": "阻止{appName}尝试下载此项目的替代版本",
|
||||
"Tasks": "任务",
|
||||
"Wanted": "已追踪",
|
||||
"Wanted": "待获取",
|
||||
"Yes": "确定",
|
||||
"AbsoluteEpisodeNumbers": "准确的集数",
|
||||
"RemoveCompleted": "移除已完成",
|
||||
@@ -688,7 +688,7 @@
|
||||
"ICalShowAsAllDayEventsHelpText": "事件将以全天事件的形式显示在日历中",
|
||||
"ICalSeasonPremieresOnlyHelpText": "每季中只有第一集会出现在订阅中",
|
||||
"IconForFinalesHelpText": "根据可用的集信息为完结的剧集或季显示图标",
|
||||
"IconForCutoffUnmet": "未达截止条件的图标",
|
||||
"IconForCutoffUnmet": "未达设定标准的图标",
|
||||
"IconForCutoffUnmetHelpText": "终止监控条件未满足前为文件显示图标",
|
||||
"IconForFinales": "剧集或季完结的图标",
|
||||
"Images": "图像",
|
||||
@@ -1459,8 +1459,8 @@
|
||||
"TotalFileSize": "文件总大小",
|
||||
"TotalRecords": "记录总数: {totalRecords}",
|
||||
"Trace": "追踪",
|
||||
"CutoffUnmetLoadError": "加载未达截止条件项目错误",
|
||||
"CutoffUnmetNoItems": "没有未达截止条件的项目",
|
||||
"CutoffUnmetLoadError": "加载未达设定标准项目时出错",
|
||||
"CutoffUnmetNoItems": "没有未达设定标准的项目",
|
||||
"DeleteSeriesFolderHelpText": "删除剧集文件夹及其所含文件",
|
||||
"DeleteSeriesModalHeader": "删除 - {title}",
|
||||
"DeletedSeriesDescription": "剧集已从 TheTVDB 移除",
|
||||
@@ -1830,5 +1830,11 @@
|
||||
"AutoTaggingSpecificationStatus": "状态",
|
||||
"ClickToChangeIndexerFlags": "点击修改索引器标志",
|
||||
"ConnectionSettingsUrlBaseHelpText": "向 {clientName} url 添加前缀,例如 {url}",
|
||||
"BlocklistFilterHasNoItems": "所选的黑名单过滤器没有项目"
|
||||
"BlocklistFilterHasNoItems": "所选的黑名单过滤器没有项目",
|
||||
"CustomFormatsSpecificationReleaseGroup": "发布组",
|
||||
"MetadataSettingsSeriesMetadata": "季元数据",
|
||||
"CustomFormatsSpecificationResolution": "分辨率",
|
||||
"CustomFormatsSpecificationSource": "来源",
|
||||
"ClickToChangeReleaseType": "点击更改发布类型",
|
||||
"CustomFormatsSettingsTriggerInfo": "当一个发布版本或文件至少匹配其中一个条件时,自定义格式将会被应用到这个版本或文件上。"
|
||||
}
|
||||
|
||||
@@ -10132,6 +10132,9 @@
|
||||
"onHealthIssue": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"includeHealthWarnings": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"onHealthRestored": {
|
||||
"type": "boolean"
|
||||
},
|
||||
@@ -10177,9 +10180,6 @@
|
||||
"supportsOnManualInteractionRequired": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"includeHealthWarnings": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"testCommand": {
|
||||
"type": "string",
|
||||
"nullable": true
|
||||
|
||||
Reference in New Issue
Block a user