Keine Mediainfo-Daten vorhanden.
; @@ -1647,6 +1732,11 @@ export default function MediaInfoReviewPanel({ const processedFiles = Number(review.processedFiles || displayTitles.length || 0); const totalFiles = Number(review.totalFiles || displayTitles.length || 0); const playlistRecommendation = review.playlistRecommendation || null; + const selectedPlaylistId = String( + review?.selectedPlaylistId + ?? review?.selectedPlaylist + ?? '' + ).trim(); const rawPreset = String(review.selectors?.preset || '').trim(); const presetLabel = String(presetDisplayValue || rawPreset).trim() || '(kein Preset)'; const multipartSettingsLock = review?.multipartSettingsLock && typeof review.multipartSettingsLock === 'object' @@ -1661,14 +1751,47 @@ export default function MediaInfoReviewPanel({ && Number(multipartSettingsLock.sourceDiscNumber) > 0 ? Math.trunc(Number(multipartSettingsLock.sourceDiscNumber)) : null; + const isTitleSelectionMode = Boolean( + review?.playlistDecisionRequired + || review?.titleSelectionRequired + || review?.handBrakeTitleDecisionRequired + ); + const playlistAlreadyAccepted = !isTitleSelectionMode && Boolean(selectedPlaylistId); + const hiddenTechnicalNotePatternsWhenPlaylistAccepted = [ + /^Preset:\s/i, + /^Extra Args:\s/i, + /^Preset-Quelle:\s/i, + /^Preset-Defaults werden als Basis genutzt\./i, + /^Preset-Hinweis:\s/i, + /^Manuelle Playlist-Auswahl aktiv:\s/i, + /^MakeMKV Full-Analyse wurde einmal für Playlist-\/Titel-Mapping verwendet\./i, + /^HandBrake Track-Analyse aktiv:\s/i + ]; + const visibleReviewNotes = Array.isArray(review.notes) + ? review.notes.filter((note) => { + const normalized = String(note || '').trim(); + if (!normalized) { + return false; + } + if (!playlistAlreadyAccepted) { + return true; + } + return !hiddenTechnicalNotePatternsWhenPlaylistAccepted + .some((pattern) => pattern.test(normalized)); + }) + : []; // User preset resolution const normalizedUserPresets = Array.isArray(userPresets) ? userPresets : []; + const normalizedHandBrakePresetOptions = Array.isArray(handBrakePresetOptions) ? handBrakePresetOptions : []; const selectedUserPreset = selectedUserPresetId ? normalizedUserPresets.find((p) => Number(p.id) === Number(selectedUserPresetId)) || null : null; const hasUserPresets = normalizedUserPresets.length > 0; - const allowUserPresetSelection = hasUserPresets && typeof onUserPresetChange === 'function' && allowEncodeItemSelection; + const hasHandBrakePresetOptions = normalizedHandBrakePresetOptions.some((option) => !option?.disabled); + const allowPresetSelection = allowEncodeItemSelection + && (typeof onUserPresetChange === 'function' || typeof onHandBrakePresetChange === 'function') + && (hasUserPresets || hasHandBrakePresetOptions); const isUserPresetActive = Boolean(selectedUserPreset); const trimmedHandBrakePreset = String(selectedHandBrakePreset || '').trim(); const isHandBrakePresetActive = !isUserPresetActive && Boolean(trimmedHandBrakePreset); @@ -1678,9 +1801,97 @@ export default function MediaInfoReviewPanel({ const effectiveAudioSelector = effectivePresetOverride?.extraArgs ? parseAudioSelectorFromArgs(effectivePresetOverride.extraArgs, review?.selectors?.audio) : (review?.selectors?.audio || null); - const presetSourceLabel = isUserPresetActive - ? `User-Preset: ${selectedUserPreset?.name || 'Preset'}` - : (isHandBrakePresetActive ? 'HandBrake-Preset' : ''); + const activePresetDisplayLabel = isUserPresetActive + ? 'User-Preset' + : ((isHandBrakePresetActive || String(presetLabel || '').trim()) ? 'HandBrake-Preset' : '(kein Preset)'); + const minLengthMinutes = Number(review?.minLengthMinutes); + const minLengthLabel = Number.isFinite(minLengthMinutes) + ? (minLengthMinutes <= 0 + ? 'Kein Mindestwert (deaktiviert)' + : `${Math.trunc(minLengthMinutes)} Minute(n)`) + : '-'; + const subtitleSelector = review?.selectors?.subtitle && typeof review.selectors.subtitle === 'object' + ? review.selectors.subtitle + : {}; + const effectiveSubtitleSelector = effectivePresetOverride?.extraArgs + ? parseSubtitleSelectorFromArgs(effectivePresetOverride.extraArgs, subtitleSelector) + : subtitleSelector; + const subtitleModeLabelMap = { + all: 'Alle Spuren', + first: 'Erste Spur', + language: 'Nach Sprache', + explicit: 'Manuell (Track-IDs)', + none: 'Keine Spuren' + }; + const subtitleModeLabel = subtitleModeLabelMap[String(effectiveSubtitleSelector?.mode || '').trim().toLowerCase()] || '-'; + const subtitleFlagLabels = []; + if (effectiveSubtitleSelector?.burnBehavior === 'first') { + subtitleFlagLabels.push('Burn-In (erste Subtitle-Spur)'); + } + if (effectiveSubtitleSelector?.defaultTrackId != null) { + subtitleFlagLabels.push(`Default-Track #${effectiveSubtitleSelector.defaultTrackId}`); + } + if (effectiveSubtitleSelector?.forcedTrackId != null) { + subtitleFlagLabels.push(`Forced-Track #${effectiveSubtitleSelector.forcedTrackId}`); + } else if (effectiveSubtitleSelector?.forcedOnly) { + subtitleFlagLabels.push('Forced-Only'); + } + const subtitleFlagsLabel = subtitleFlagLabels.join(', ') || 'Keine'; + const audioEncoderSourceLabel = String(effectiveAudioSelector?.encoderSource || '').trim() || 'default'; + const audioCopyMaskSourceLabel = String(effectiveAudioSelector?.copyMaskSource || '').trim() || 'default'; + const audioFallbackSourceLabel = String(effectiveAudioSelector?.fallbackSource || '').trim() || 'default'; + const presetDropdownOptions = (() => { + const options = []; + if (hasUserPresets) { + options.push({ label: 'User-Presets/', value: '__group__userpresets', disabled: true }); + for (const preset of normalizedUserPresets) { + const presetId = Number(preset?.id); + if (!Number.isFinite(presetId) || presetId <= 0) { + continue; + } + const mediaType = String(preset?.mediaType || '').trim().toLowerCase(); + const mediaTypeLabel = mediaType && mediaType !== 'all' + ? ` [${mediaType === 'bluray' ? 'Blu-ray' : mediaType === 'dvd' ? 'DVD' : mediaType}]` + : ''; + options.push({ + label: `\u00A0\u00A0\u00A0${String(preset?.name || `Preset #${presetId}`).trim() || `Preset #${presetId}`}${mediaTypeLabel}`, + value: `user:${Math.trunc(presetId)}` + }); + } + } + for (const option of normalizedHandBrakePresetOptions) { + if (!option) { + continue; + } + if (option.disabled) { + options.push({ + label: String(option?.label || '').trim() || 'HandBrake/', + value: String(option?.value || option?.label || '').trim() || `__group__hb_${options.length}`, + disabled: true + }); + continue; + } + const value = String(option?.value || '').trim(); + if (!value) { + continue; + } + options.push({ + label: String(option?.label || value).trim() || value, + value: `hb:${value}` + }); + } + const selectedPresetValue = String(selectedHandBrakePreset || '').trim(); + if (selectedPresetValue && !options.some((entry) => String(entry?.value || '').trim() === `hb:${selectedPresetValue}`)) { + options.push({ + label: selectedPresetValue, + value: `hb:${selectedPresetValue}` + }); + } + return options; + })(); + const selectedPresetToken = isUserPresetActive + ? `user:${selectedUserPreset.id}` + : (trimmedHandBrakePreset ? `hb:${trimmedHandBrakePreset}` : null); const scriptCatalog = (Array.isArray(availableScripts) ? availableScripts : []) .map((item) => ({ @@ -1872,22 +2083,42 @@ export default function MediaInfoReviewPanel({ return (Inbox wird geladen ...
- ) : filteredRows.length === 0 ? ( -Keine Jobs für den aktuellen Filter gefunden.
- ) : ( - pagedRows.map(({ job, meta }) => { - const jobId = normalizeJobId(job?.id); - if (!jobId) { - return null; - } - const isQueued = queuedJobIds.has(jobId); - const normalizedStatus = normalizeStatus(job?.status); - const targetPath = meta.family === 'converter' ? '/converter' : '/ripper'; - const jobTitle = String(job?.title || job?.detected_title || '').trim() || `Job #${jobId}`; - return ( -