0.14.0 BluRay Series Flow
This commit is contained in:
@@ -486,6 +486,34 @@ function normalizePositiveInt(value) {
|
||||
return Math.trunc(parsed);
|
||||
}
|
||||
|
||||
function hasSeriesMetadataShape(source = null) {
|
||||
const metadata = source && typeof source === 'object' ? source : {};
|
||||
const seasonNumber = normalizePositiveInt(metadata?.seasonNumber ?? metadata?.season ?? null);
|
||||
const episodes = Array.isArray(metadata?.episodes) ? metadata.episodes : [];
|
||||
const metadataProvider = String(metadata?.metadataProvider || '').trim().toLowerCase();
|
||||
const workflowKind = String(metadata?.workflowKind || metadata?.kind || '').trim().toLowerCase();
|
||||
return Boolean(
|
||||
seasonNumber
|
||||
|| episodes.length > 0
|
||||
|| metadataProvider === 'tmdb'
|
||||
|| metadataProvider === 'themoviedb'
|
||||
|| workflowKind === 'series'
|
||||
|| workflowKind === 'season'
|
||||
);
|
||||
}
|
||||
|
||||
function hasSeriesEpisodeAssignmentHints(titles = []) {
|
||||
const reviewTitles = Array.isArray(titles) ? titles : [];
|
||||
return reviewTitles.some((title) => {
|
||||
const seasonNumber = normalizePositiveInt(title?.seasonNumber ?? title?.season ?? null);
|
||||
const episodeNumber = normalizePositiveInt(title?.episodeNumber ?? title?.number ?? null);
|
||||
const episodeId = normalizePositiveInt(title?.episodeId ?? null);
|
||||
const episodeTitle = String(title?.episodeTitle || '').trim();
|
||||
const episodeTitleStart = String(title?.episodeTitleStart || '').trim();
|
||||
return Boolean(seasonNumber || episodeNumber || episodeId || episodeTitle || episodeTitleStart);
|
||||
});
|
||||
}
|
||||
|
||||
function normalizeEpisodeReference(entry = {}) {
|
||||
const source = entry && typeof entry === 'object' ? entry : {};
|
||||
const episodeId = normalizePositiveInt(source?.episodeId ?? source?.id ?? null);
|
||||
@@ -605,6 +633,20 @@ function normalizeSeriesLanguage(value) {
|
||||
return raw;
|
||||
}
|
||||
|
||||
function normalizeSeriesTitleForOutputPath(value, fallback = 'series') {
|
||||
const raw = String(value || '').trim();
|
||||
if (!raw) {
|
||||
return String(fallback || 'series').trim() || 'series';
|
||||
}
|
||||
const stripped = raw
|
||||
.replace(/\s*-\s*S\d{1,2}E\d{1,3}(?:-\d{1,3})?\b.*$/i, '')
|
||||
.trim();
|
||||
if (stripped) {
|
||||
return stripped;
|
||||
}
|
||||
return raw;
|
||||
}
|
||||
|
||||
function normalizeSeriesBatchStatus(value) {
|
||||
return String(value || '').trim().toUpperCase() || 'UNKNOWN';
|
||||
}
|
||||
@@ -1061,6 +1103,7 @@ function buildFallbackEpisodeTitleForOutput(episodeRange = null, template = '')
|
||||
|
||||
function buildDvdSeriesEpisodeOutputPathPreview(
|
||||
settings,
|
||||
mediaProfile,
|
||||
metadata,
|
||||
title,
|
||||
assignment = null,
|
||||
@@ -1069,9 +1112,13 @@ function buildDvdSeriesEpisodeOutputPathPreview(
|
||||
assignmentByTitle = {},
|
||||
selectedTitleIds = []
|
||||
) {
|
||||
const normalizedSeriesMediaProfile = String(mediaProfile || '').trim().toLowerCase() === 'bluray'
|
||||
? 'bluray'
|
||||
: 'dvd';
|
||||
const seriesRootDir = String(
|
||||
settings?.series_dir_dvd
|
||||
|| settings?.movie_dir_dvd
|
||||
(normalizedSeriesMediaProfile === 'bluray'
|
||||
? (settings?.series_dir_bluray || settings?.series_dir_dvd || settings?.movie_dir_bluray || settings?.movie_dir_dvd)
|
||||
: (settings?.series_dir_dvd || settings?.series_dir_bluray || settings?.movie_dir_dvd || settings?.movie_dir_bluray))
|
||||
|| settings?.movie_dir
|
||||
|| ''
|
||||
).trim();
|
||||
@@ -1105,21 +1152,29 @@ function buildDvdSeriesEpisodeOutputPathPreview(
|
||||
const episodeRangeToken = buildEpisodeRangeToken(effectiveEpisodeRange.start, effectiveEpisodeRange.end);
|
||||
const partsToken = buildEpisodePartsToken(effectiveEpisodeRange);
|
||||
const discNumber = normalizePositiveInt(metadata?.discNumber ?? assignment?.discNumber ?? null);
|
||||
const seriesTitleRaw = String(
|
||||
metadata?.title
|
||||
|| metadata?.seriesTitle
|
||||
|| (fallbackJobId ? `job-${fallbackJobId}` : 'series')
|
||||
).trim();
|
||||
const seriesTitle = seriesTitleRaw || 'series';
|
||||
const seriesTitle = normalizeSeriesTitleForOutputPath(
|
||||
metadata?.seriesTitle
|
||||
|| metadata?.title
|
||||
|| (fallbackJobId ? `job-${fallbackJobId}` : 'series'),
|
||||
fallbackJobId ? `job-${fallbackJobId}` : 'series'
|
||||
);
|
||||
const year = String(metadata?.year || new Date().getFullYear()).trim();
|
||||
const language = normalizeSeriesLanguage(settings?.dvd_series_language || metadata?.language || null);
|
||||
|
||||
const singleTemplateRaw = String(
|
||||
settings?.output_template_dvd_series_episode
|
||||
(normalizedSeriesMediaProfile === 'bluray'
|
||||
? settings?.output_template_bluray_series_episode
|
||||
: settings?.output_template_dvd_series_episode)
|
||||
|| settings?.output_template_dvd_series_episode
|
||||
|| settings?.output_template_bluray_series_episode
|
||||
|| '{seriesTitle}/Staffel {seasonNr}/S{seasonNr}E{episodeNr} - {episodeTitle}'
|
||||
).trim();
|
||||
const multiTemplateRaw = String(
|
||||
settings?.output_template_dvd_series_multi_episode
|
||||
(normalizedSeriesMediaProfile === 'bluray'
|
||||
? settings?.output_template_bluray_series_multi_episode
|
||||
: settings?.output_template_dvd_series_multi_episode)
|
||||
|| settings?.output_template_dvd_series_multi_episode
|
||||
|| settings?.output_template_bluray_series_multi_episode
|
||||
|| '{seriesTitle}/Staffel {seasonNr}/S{0:seasonNr}E{episodeRange} - {episodeTitle} (Teil {parts})'
|
||||
).trim();
|
||||
const singleTemplate = singleTemplateRaw || '{seriesTitle}/Staffel {seasonNr}/S{seasonNr}E{episodeNr} - {episodeTitle}';
|
||||
@@ -1160,7 +1215,15 @@ function buildDvdSeriesEpisodeOutputPathPreview(
|
||||
.filter(Boolean);
|
||||
const baseName = segments.length > 0 ? segments[segments.length - 1] : 'untitled';
|
||||
const folderParts = segments.slice(0, -1);
|
||||
const ext = String(settings?.output_extension_dvd || settings?.output_extension || 'mkv').trim() || 'mkv';
|
||||
const ext = String(
|
||||
(normalizedSeriesMediaProfile === 'bluray'
|
||||
? settings?.output_extension_bluray
|
||||
: settings?.output_extension_dvd)
|
||||
|| settings?.output_extension_dvd
|
||||
|| settings?.output_extension_bluray
|
||||
|| settings?.output_extension
|
||||
|| 'mkv'
|
||||
).trim() || 'mkv';
|
||||
const root = seriesRootDir.replace(/\/+$/g, '');
|
||||
if (folderParts.length > 0) {
|
||||
return `${root}/${folderParts.join('/')}/${baseName}.${ext}`;
|
||||
@@ -1304,8 +1367,9 @@ export default function PipelineStatusCard({
|
||||
const reviewMode = String(mediaInfoReview?.mode || '').trim().toLowerCase();
|
||||
const isPreRipReview = reviewMode === 'pre_rip' || Boolean(mediaInfoReview?.preRip);
|
||||
const jobMediaProfile = resolvePipelineMediaProfile(pipeline, mediaInfoReview);
|
||||
const isDvdTitleSelectionRequired = Boolean(
|
||||
jobMediaProfile === 'dvd'
|
||||
const discTypeLabel = jobMediaProfile === 'bluray' ? 'Blu-ray' : 'DVD';
|
||||
const isDiscTitleSelectionRequired = Boolean(
|
||||
(jobMediaProfile === 'dvd' || jobMediaProfile === 'bluray')
|
||||
&& (mediaInfoReview?.titleSelectionRequired || mediaInfoReview?.handBrakeTitleDecisionRequired)
|
||||
);
|
||||
const [liveJobLog, setLiveJobLog] = useState('');
|
||||
@@ -1467,8 +1531,21 @@ export default function PipelineStatusCard({
|
||||
...reviewTitles.filter((title) => Boolean(title?.selectedForEncode)).map((title) => title?.id),
|
||||
...(fromReview ? [fromReview] : [])
|
||||
]);
|
||||
const isSeriesVideoByMetadata = Boolean(
|
||||
(jobMediaProfile === 'dvd' || jobMediaProfile === 'bluray')
|
||||
&& (
|
||||
hasSeriesMetadataShape(selectedMetadata)
|
||||
|| hasSeriesMetadataShape(mediaInfoReview?.selectedMetadata)
|
||||
|| hasSeriesEpisodeAssignmentHints(reviewTitles)
|
||||
|| Boolean(mediaInfoReview?.seriesBatchParent)
|
||||
)
|
||||
);
|
||||
const defaultAllTitles = Boolean(
|
||||
(mediaInfoReview?.titleSelectionRequired || mediaInfoReview?.handBrakeTitleDecisionRequired)
|
||||
(
|
||||
mediaInfoReview?.titleSelectionRequired
|
||||
|| mediaInfoReview?.handBrakeTitleDecisionRequired
|
||||
|| (isSeriesVideoByMetadata && reviewTitles.length > 1)
|
||||
)
|
||||
&& reviewTitles.length > 0
|
||||
);
|
||||
const effectiveSelected = defaultAllTitles
|
||||
@@ -1537,6 +1614,10 @@ export default function PipelineStatusCard({
|
||||
mediaInfoReview?.outputFormat,
|
||||
mediaInfoReview?.userPreset?.id,
|
||||
mediaInfoReview?.userPreset?.handbrakePreset,
|
||||
selectedMetadata?.seasonNumber,
|
||||
selectedMetadata?.episodes,
|
||||
selectedMetadata?.metadataProvider,
|
||||
jobMediaProfile,
|
||||
retryJobId
|
||||
]);
|
||||
|
||||
@@ -1877,16 +1958,6 @@ export default function PipelineStatusCard({
|
||||
if (!Array.isArray(selectedMetadataEpisodes) || selectedMetadataEpisodes.length === 0) {
|
||||
return;
|
||||
}
|
||||
const hasAnyEpisodeAssignment = Object.values(episodeAssignmentsByTitle || {}).some((assignment) => {
|
||||
const episodeId = Number(assignment?.episodeId || 0);
|
||||
const episodeNumber = Number(assignment?.episodeNumber || 0);
|
||||
const seasonNumber = Number(assignment?.seasonNumber || 0);
|
||||
const episodeTitle = String(assignment?.episodeTitle || '').trim();
|
||||
return Boolean(episodeTitle || episodeId > 0 || episodeNumber > 0 || seasonNumber > 0);
|
||||
});
|
||||
if (hasAnyEpisodeAssignment) {
|
||||
return;
|
||||
}
|
||||
if (!Array.isArray(episodeFillOptions) || episodeFillOptions.length === 0) {
|
||||
return;
|
||||
}
|
||||
@@ -1903,11 +1974,64 @@ export default function PipelineStatusCard({
|
||||
}
|
||||
if (!hasValidSelection) {
|
||||
setSelectedEpisodeFillStart(String(defaultStartRef));
|
||||
// Keep dropdown + episodentitel in sync when options change (e.g. Disc 2
|
||||
// after already used episodes were loaded from the container).
|
||||
applyEpisodeFillFrom(defaultStartRef);
|
||||
return;
|
||||
}
|
||||
|
||||
const reviewTitles = Array.isArray(mediaInfoReview?.titles) ? mediaInfoReview.titles : [];
|
||||
const fallbackSelectedIds = normalizeTitleIdList([
|
||||
...selectedEncodeTitleIds,
|
||||
selectedEncodeTitleId,
|
||||
mediaInfoReview?.encodeInputTitleId,
|
||||
...reviewTitles.filter((title) => Boolean(title?.selectedForEncode)).map((title) => title?.id)
|
||||
]);
|
||||
const selectedTitleIdsInReviewOrder = reviewTitles
|
||||
.map((title) => normalizeTitleId(title?.id))
|
||||
.filter((id) => id !== null && fallbackSelectedIds.includes(id));
|
||||
const effectiveSelectedTitleIds = selectedTitleIdsInReviewOrder.length > 0
|
||||
? selectedTitleIdsInReviewOrder
|
||||
: fallbackSelectedIds;
|
||||
|
||||
const hasEpisodeAssignmentPayload = (assignment) => {
|
||||
if (!assignment || typeof assignment !== 'object') {
|
||||
return false;
|
||||
}
|
||||
const episodeId = Number(assignment?.episodeId || assignment?.episodeIdStart || 0);
|
||||
const episodeNumber = Number(assignment?.episodeNumber || assignment?.episodeNumberStart || 0);
|
||||
const seasonNumber = Number(assignment?.seasonNumber || 0);
|
||||
const episodeTitle = String(assignment?.episodeTitle || '').trim();
|
||||
return Boolean(episodeTitle || episodeId > 0 || episodeNumber > 0 || seasonNumber > 0);
|
||||
};
|
||||
|
||||
const hasAnyEpisodeAssignment = effectiveSelectedTitleIds.some((titleId) => {
|
||||
const assignment = episodeAssignmentsByTitle?.[titleId]
|
||||
|| episodeAssignmentsByTitle?.[String(titleId)]
|
||||
|| null;
|
||||
return hasEpisodeAssignmentPayload(assignment);
|
||||
});
|
||||
const hasCompleteEpisodeAssignments = effectiveSelectedTitleIds.length > 0
|
||||
&& effectiveSelectedTitleIds.every((titleId) => {
|
||||
const assignment = episodeAssignmentsByTitle?.[titleId]
|
||||
|| episodeAssignmentsByTitle?.[String(titleId)]
|
||||
|| null;
|
||||
return hasEpisodeAssignmentPayload(assignment);
|
||||
});
|
||||
|
||||
if (hasCompleteEpisodeAssignments) {
|
||||
return;
|
||||
}
|
||||
if (hasAnyEpisodeAssignment && normalizedSelection) {
|
||||
return;
|
||||
}
|
||||
applyEpisodeFillFrom(defaultStartRef);
|
||||
}, [
|
||||
selectedMetadataEpisodes,
|
||||
selectedEncodeTitleIds,
|
||||
selectedEncodeTitleId,
|
||||
mediaInfoReview?.titles,
|
||||
mediaInfoReview?.encodeInputTitleId,
|
||||
mediaInfoReview?.generatedAt,
|
||||
episodeAssignmentsByTitle,
|
||||
episodeFillOptions,
|
||||
@@ -2247,6 +2371,16 @@ export default function PipelineStatusCard({
|
||||
pipeline?.context?.selectedPlaylist
|
||||
]);
|
||||
|
||||
const seriesBatchRunningChildJobIdHint = useMemo(() => {
|
||||
const seriesBatch = pipeline?.context?.seriesBatch;
|
||||
if (!seriesBatch || typeof seriesBatch !== 'object') {
|
||||
return null;
|
||||
}
|
||||
const children = Array.isArray(seriesBatch?.children) ? seriesBatch.children : [];
|
||||
const runningChild = children.find((child) => normalizeSeriesBatchStatus(child?.status) === 'RUNNING') || null;
|
||||
return normalizeJobId(runningChild?.jobId);
|
||||
}, [pipeline?.context?.seriesBatch]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!running || !retryJobId) {
|
||||
setLiveJobLog('');
|
||||
@@ -2257,7 +2391,38 @@ export default function PipelineStatusCard({
|
||||
try {
|
||||
const response = await api.getJob(retryJobId, { includeLiveLog: true, lite: true });
|
||||
if (!cancelled) {
|
||||
setLiveJobLog(response?.job?.log || '');
|
||||
const liveJob = response?.job && typeof response.job === 'object'
|
||||
? response.job
|
||||
: null;
|
||||
const childRows = Array.isArray(liveJob?.children) ? liveJob.children : [];
|
||||
const liveHintChildId = normalizeJobId(seriesBatchRunningChildJobIdHint);
|
||||
const isSeriesBatchParentRun = Boolean(
|
||||
liveHintChildId
|
||||
|| liveJob?.encodePlan?.seriesBatchParent
|
||||
|| String(liveJob?.handbrakeInfo?.mode || '').trim().toLowerCase() === 'series_batch'
|
||||
);
|
||||
|
||||
if (isSeriesBatchParentRun) {
|
||||
const activeChildStates = new Set(['ANALYZING', 'RIPPING', 'MEDIAINFO_CHECK', 'ENCODING', 'RUNNING']);
|
||||
let activeChild = liveHintChildId
|
||||
? (childRows.find((child) => normalizeJobId(child?.id) === liveHintChildId) || null)
|
||||
: null;
|
||||
if (activeChild) {
|
||||
const hintChildStatus = String(activeChild?.status || activeChild?.last_state || '').trim().toUpperCase();
|
||||
if (!activeChildStates.has(hintChildStatus)) {
|
||||
activeChild = null;
|
||||
}
|
||||
}
|
||||
if (!activeChild) {
|
||||
activeChild = childRows.find((child) => (
|
||||
activeChildStates.has(String(child?.status || child?.last_state || '').trim().toUpperCase())
|
||||
)) || null;
|
||||
}
|
||||
setLiveJobLog(String(activeChild?.log || '').trim());
|
||||
return;
|
||||
}
|
||||
|
||||
setLiveJobLog(String(liveJob?.log || '').trim());
|
||||
}
|
||||
} catch (_err) {
|
||||
// ignore transient polling errors
|
||||
@@ -2269,22 +2434,34 @@ export default function PipelineStatusCard({
|
||||
cancelled = true;
|
||||
clearInterval(interval);
|
||||
};
|
||||
}, [running, retryJobId]);
|
||||
}, [running, retryJobId, seriesBatchRunningChildJobIdHint]);
|
||||
|
||||
const manualDecisionState = pipeline?.context?.manualDecisionState || null;
|
||||
const rawDecisionRequiredBeforeStart = state === 'WAITING_FOR_USER_DECISION' && manualDecisionState === 'waiting_for_raw_decision';
|
||||
const playlistDecisionRequiredBeforeStart = state === 'WAITING_FOR_USER_DECISION' && !handBrakeTitleDecisionRequired && !rawDecisionRequiredBeforeStart;
|
||||
const isSeriesDvdReview = useMemo(() => {
|
||||
if (jobMediaProfile !== 'dvd') {
|
||||
if (jobMediaProfile !== 'dvd' && jobMediaProfile !== 'bluray') {
|
||||
return false;
|
||||
}
|
||||
const seasonNumberRaw = selectedMetadata?.seasonNumber ?? null;
|
||||
const seasonNumber = Number(String(seasonNumberRaw ?? '').replace(',', '.'));
|
||||
const hasSeasonNumber = Number.isFinite(seasonNumber) && seasonNumber > 0;
|
||||
const hasEpisodeList = Array.isArray(selectedMetadata?.episodes) && selectedMetadata.episodes.length > 0;
|
||||
const metadataProvider = String(selectedMetadata?.metadataProvider || '').trim().toLowerCase();
|
||||
return hasSeasonNumber || hasEpisodeList || metadataProvider === 'tmdb' || metadataProvider === 'themoviedb';
|
||||
}, [jobMediaProfile, selectedMetadata?.seasonNumber, selectedMetadata?.episodes, selectedMetadata?.metadataProvider]);
|
||||
return Boolean(
|
||||
hasSeriesMetadataShape(selectedMetadata)
|
||||
|| hasSeriesMetadataShape(mediaInfoReview?.selectedMetadata)
|
||||
|| hasSeriesEpisodeAssignmentHints(mediaInfoReview?.titles)
|
||||
|| Boolean(mediaInfoReview?.seriesBatchParent)
|
||||
);
|
||||
}, [
|
||||
jobMediaProfile,
|
||||
selectedMetadata?.seasonNumber,
|
||||
selectedMetadata?.episodes,
|
||||
selectedMetadata?.metadataProvider,
|
||||
selectedMetadata?.workflowKind,
|
||||
mediaInfoReview?.selectedMetadata?.seasonNumber,
|
||||
mediaInfoReview?.selectedMetadata?.episodes,
|
||||
mediaInfoReview?.selectedMetadata?.metadataProvider,
|
||||
mediaInfoReview?.selectedMetadata?.workflowKind,
|
||||
mediaInfoReview?.titles,
|
||||
mediaInfoReview?.seriesBatchParent
|
||||
]);
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
|
||||
@@ -2515,6 +2692,7 @@ export default function PipelineStatusCard({
|
||||
|| null;
|
||||
const path = buildDvdSeriesEpisodeOutputPathPreview(
|
||||
settingsMap,
|
||||
jobMediaProfile,
|
||||
selectedMetadata || {},
|
||||
title,
|
||||
assignment,
|
||||
@@ -2533,6 +2711,7 @@ export default function PipelineStatusCard({
|
||||
mediaInfoReview?.titles,
|
||||
episodeAssignmentsByTitle,
|
||||
settingsMap,
|
||||
jobMediaProfile,
|
||||
selectedMetadata,
|
||||
retryJobId,
|
||||
selectedEncodeTitleIds
|
||||
@@ -3091,7 +3270,7 @@ export default function PipelineStatusCard({
|
||||
|
||||
{handBrakeTitleDecisionRequired && retryJobId && (
|
||||
<Button
|
||||
label={isSeriesPlayAllDecisionMode ? 'PlayAll/Doppelfolge bestätigen' : 'DVD Titel bestätigen'}
|
||||
label={isSeriesPlayAllDecisionMode ? 'PlayAll/Doppelfolge bestätigen' : `${discTypeLabel} Titel bestätigen`}
|
||||
icon="pi pi-check"
|
||||
severity="warning"
|
||||
outlined
|
||||
@@ -3353,11 +3532,11 @@ export default function PipelineStatusCard({
|
||||
|
||||
{handBrakeTitleDecisionRequired && !queueLocked ? (
|
||||
<div className="playlist-decision-block">
|
||||
<h3>{isSeriesPlayAllDecisionMode ? 'Serien-Grenzfall: PlayAll oder Doppelfolge?' : 'DVD Titel-Auswahl erforderlich'}</h3>
|
||||
<h3>{isSeriesPlayAllDecisionMode ? 'Serien-Grenzfall: PlayAll oder Doppelfolge?' : `${discTypeLabel} Titelauswahl erforderlich`}</h3>
|
||||
<small>
|
||||
{isSeriesPlayAllDecisionMode
|
||||
? 'Min. ein Titel passt zeitlich zur Summe der kürzeren Episoden. Bitte durch Auswahl entscheiden, ob PlayAll Multi-Episode (nicht anhaken) oder Doppelfolge (anhaken).'
|
||||
: 'Mehrere DVD-Titel gefunden, die die Mindestlänge erfüllen. Bitte einen oder mehrere Episoden-Titel auswählen.'}
|
||||
: `Mehrere ${discTypeLabel}-Titel gefunden, die die Mindestlänge erfüllen. Bitte einen oder mehrere Episodentitel auswählen.`}
|
||||
</small>
|
||||
{visibleWaitingHandBrakeTitleRows.length > 0 ? (
|
||||
<div className="playlist-decision-list">
|
||||
@@ -3415,7 +3594,7 @@ export default function PipelineStatusCard({
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{selectedMetadata && !isDvdTitleSelectionRequired ? (
|
||||
{selectedMetadata && !isDiscTitleSelectionRequired ? (
|
||||
<div className="pipeline-meta-inline">
|
||||
{selectedMetadata.poster ? (
|
||||
<img
|
||||
@@ -3445,8 +3624,8 @@ export default function PipelineStatusCard({
|
||||
|
||||
{(state === 'READY_TO_ENCODE' || state === 'MEDIAINFO_CHECK' || mediaInfoReview) && !(handBrakeTitleDecisionRequired && isSeriesPlayAllDecisionMode) ? (
|
||||
<div className="mediainfo-review-block">
|
||||
{!isDvdTitleSelectionRequired ? <h3>Titel-/Spurprüfung</h3> : null}
|
||||
{state === 'READY_TO_ENCODE' && !queueLocked && !isDvdTitleSelectionRequired ? (
|
||||
{!isDiscTitleSelectionRequired ? <h3>Titel-/Spurprüfung</h3> : null}
|
||||
{state === 'READY_TO_ENCODE' && !queueLocked && !isDiscTitleSelectionRequired ? (
|
||||
<small>
|
||||
{isPreRipReview
|
||||
? 'Spurauswahl kann direkt übernommen werden. Beim Klick auf "Backup + Encoding starten" wird automatisch bestätigt und gestartet.'
|
||||
@@ -3543,7 +3722,7 @@ export default function PipelineStatusCard({
|
||||
<div className="playlist-decision-block">
|
||||
<h3>Hinweis Episoden-Zuordnung</h3>
|
||||
<small>
|
||||
Im Job wurden Hinweise zur Episoden-Zuordnung erkannt. Bitte Episodentitel und Episodenbereich pruefen, bevor das Encoding startet.
|
||||
Im Job wurden Hinweise zur Episoden-Zuordnung erkannt. Bitte Episodentitel und Episodenbereich prüfen, bevor das Encoding startet.
|
||||
</small>
|
||||
{episodeAssignmentWarningLines.map((line, index) => (
|
||||
<small key={`episode-assignment-warning-${index}`}>{line}</small>
|
||||
@@ -3558,7 +3737,7 @@ export default function PipelineStatusCard({
|
||||
selectedEncodeTitleId={normalizeTitleId(selectedEncodeTitleId)}
|
||||
selectedEncodeTitleIds={normalizeTitleIdList(selectedEncodeTitleIds)}
|
||||
allowTitleSelection={(state === 'READY_TO_ENCODE' || state === 'WAITING_FOR_USER_DECISION') && !queueLocked}
|
||||
compactTitleSelection={isDvdTitleSelectionRequired}
|
||||
compactTitleSelection={isDiscTitleSelectionRequired}
|
||||
onSelectEncodeTitle={(titleId) => {
|
||||
const normalizedTitleId = normalizeTitleId(titleId);
|
||||
setSelectedEncodeTitleId(normalizedTitleId);
|
||||
|
||||
Reference in New Issue
Block a user