0.13.1-5 Adjust Detection
This commit is contained in:
@@ -4,6 +4,7 @@ import { Button } from 'primereact/button';
|
||||
import { DataTable } from 'primereact/datatable';
|
||||
import { Column } from 'primereact/column';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { Dropdown } from 'primereact/dropdown';
|
||||
|
||||
export default function MetadataSelectionDialog({
|
||||
visible,
|
||||
@@ -36,12 +37,20 @@ export default function MetadataSelectionDialog({
|
||||
const [submitError, setSubmitError] = useState('');
|
||||
const [seasonFilter, setSeasonFilter] = useState('');
|
||||
const [discValidationError, setDiscValidationError] = useState('');
|
||||
const metadataProvider = String(context?.metadataProvider || 'omdb').trim().toLowerCase() || 'omdb';
|
||||
const contextMetadataProvider = String(context?.metadataProvider || 'omdb').trim().toLowerCase() || 'omdb';
|
||||
const [selectedMetadataProvider, setSelectedMetadataProvider] = useState(contextMetadataProvider);
|
||||
const mediaProfile = String(
|
||||
context?.mediaProfile
|
||||
|| context?.selectedMetadata?.mediaProfile
|
||||
|| ''
|
||||
).trim().toLowerCase();
|
||||
const metadataProvider = selectedMetadataProvider === 'tmdb' ? 'tmdb' : 'omdb';
|
||||
const providerOptions = mediaProfile === 'dvd'
|
||||
? [
|
||||
{ label: 'Film (OMDb)', value: 'omdb' },
|
||||
{ label: 'Serie (TMDb)', value: 'tmdb' }
|
||||
]
|
||||
: [{ label: contextMetadataProvider === 'tmdb' ? 'TMDb' : 'OMDb', value: contextMetadataProvider }];
|
||||
const providerLabel = metadataProvider === 'tmdb' ? 'TMDb' : 'OMDb';
|
||||
const supportsExternalIdInput = metadataProvider === 'omdb';
|
||||
const requiresDiscNumber = metadataProvider === 'tmdb' && (mediaProfile === 'dvd' || !mediaProfile);
|
||||
@@ -70,6 +79,7 @@ export default function MetadataSelectionDialog({
|
||||
setSubmitError('');
|
||||
setSeasonFilter('');
|
||||
setDiscValidationError('');
|
||||
setSelectedMetadataProvider(contextMetadataProvider);
|
||||
}, [visible, context]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -85,7 +95,7 @@ export default function MetadataSelectionDialog({
|
||||
if (submitError) {
|
||||
setSubmitError('');
|
||||
}
|
||||
}, [manualDiscNumber, seasonFilter, selected]);
|
||||
}, [manualDiscNumber, seasonFilter, selected, metadataProvider]);
|
||||
|
||||
const rows = useMemo(() => {
|
||||
const base = Array.isArray(context?.metadataCandidates)
|
||||
@@ -240,6 +250,25 @@ export default function MetadataSelectionDialog({
|
||||
modal
|
||||
>
|
||||
<div className="search-row">
|
||||
{providerOptions.length > 1 ? (
|
||||
<Dropdown
|
||||
value={metadataProvider}
|
||||
options={providerOptions}
|
||||
optionLabel="label"
|
||||
optionValue="value"
|
||||
onChange={(event) => {
|
||||
const nextProvider = String(event?.value || 'omdb').trim().toLowerCase() || 'omdb';
|
||||
setSelectedMetadataProvider(nextProvider);
|
||||
setSelected(null);
|
||||
setExtraResults([]);
|
||||
setSearchError('');
|
||||
setSubmitError('');
|
||||
setDiscValidationError('');
|
||||
}}
|
||||
disabled={searchBusy || busy}
|
||||
style={{ minWidth: '12.5rem' }}
|
||||
/>
|
||||
) : null}
|
||||
<InputText
|
||||
value={query}
|
||||
onChange={(event) => setQuery(event.target.value)}
|
||||
|
||||
@@ -985,10 +985,10 @@ function buildDvdSeriesEpisodeOutputPathPreview(settings, metadata, title, assig
|
||||
).trim();
|
||||
const multiTemplateRaw = String(
|
||||
settings?.output_template_dvd_series_multi_episode
|
||||
|| '{seriesTitle}/Staffel {seasonNr}/S{seasonNr}E{episodeRange}'
|
||||
|| '{seriesTitle}/Staffel {seasonNr}/S{0:seasonNr}E{episodeRange} - {episodeTitle} (Teil {parts})'
|
||||
).trim();
|
||||
const singleTemplate = singleTemplateRaw || '{seriesTitle}/Staffel {seasonNr}/S{seasonNr}E{episodeNr} - {episodeTitle}';
|
||||
const multiTemplate = multiTemplateRaw || '{seriesTitle}/Staffel {seasonNr}/S{seasonNr}E{episodeRange}';
|
||||
const multiTemplate = multiTemplateRaw || '{seriesTitle}/Staffel {seasonNr}/S{0:seasonNr}E{episodeRange} - {episodeTitle} (Teil {parts})';
|
||||
const template = episodeRange.isMulti ? multiTemplate : singleTemplate;
|
||||
const rendered = renderTemplate(template, {
|
||||
seriesTitle,
|
||||
@@ -1936,6 +1936,13 @@ export default function PipelineStatusCard({
|
||||
|
||||
const handBrakeTitleDecisionRequired = state === 'WAITING_FOR_USER_DECISION'
|
||||
&& Boolean(pipeline?.context?.handBrakeTitleDecisionRequired);
|
||||
const handBrakeDecisionMode = String(pipeline?.context?.handBrakeDecisionMode || '').trim().toLowerCase();
|
||||
const isSeriesPlayAllDecisionMode = handBrakeDecisionMode === 'series_playall_or_double';
|
||||
const handBrakeDecisionSummary = pipeline?.context?.handBrakeDecisionSummary
|
||||
&& typeof pipeline.context.handBrakeDecisionSummary === 'object'
|
||||
? pipeline.context.handBrakeDecisionSummary
|
||||
: null;
|
||||
const ambiguousLongestTitleId = normalizeTitleId(handBrakeDecisionSummary?.longestCandidateTitleId);
|
||||
|
||||
const waitingHandBrakeTitleRows = useMemo(() => {
|
||||
const raw = Array.isArray(pipeline?.context?.handBrakeTitleCandidates)
|
||||
@@ -2849,7 +2856,7 @@ export default function PipelineStatusCard({
|
||||
|
||||
{handBrakeTitleDecisionRequired && retryJobId && (
|
||||
<Button
|
||||
label="DVD Titel bestätigen"
|
||||
label={isSeriesPlayAllDecisionMode ? 'PlayAll/Doppelfolge bestätigen' : 'DVD Titel bestätigen'}
|
||||
icon="pi pi-check"
|
||||
severity="warning"
|
||||
outlined
|
||||
@@ -3077,9 +3084,11 @@ export default function PipelineStatusCard({
|
||||
|
||||
{handBrakeTitleDecisionRequired && !queueLocked ? (
|
||||
<div className="playlist-decision-block">
|
||||
<h3>DVD Titel-Auswahl erforderlich</h3>
|
||||
<h3>{isSeriesPlayAllDecisionMode ? 'Serien-Grenzfall: PlayAll oder Doppelfolge?' : 'DVD Titel-Auswahl erforderlich'}</h3>
|
||||
<small>
|
||||
Mehrere DVD-Titel gefunden, die die Mindestlänge erfüllen. Bitte einen oder mehrere Episoden-Titel auswählen.
|
||||
{isSeriesPlayAllDecisionMode
|
||||
? 'Grenzfall erkannt: Der längste Titel passt zeitlich zur Summe der kürzeren Episoden. Bitte entscheiden, ob er als PlayAll ausgeschlossen oder als Doppelfolge mit encodiert werden soll.'
|
||||
: 'Mehrere DVD-Titel gefunden, die die Mindestlänge erfüllen. Bitte einen oder mehrere Episoden-Titel auswählen.'}
|
||||
</small>
|
||||
{waitingHandBrakeTitleRows.length > 0 ? (
|
||||
<div className="playlist-decision-list">
|
||||
@@ -3102,6 +3111,9 @@ export default function PipelineStatusCard({
|
||||
/>
|
||||
<span>
|
||||
{`Titel -t ${row.handBrakeTitleId}`}
|
||||
{isSeriesPlayAllDecisionMode && ambiguousLongestTitleId && row.handBrakeTitleId === ambiguousLongestTitleId
|
||||
? ' | Längster Titel (PlayAll-/Doppelfolge-Kandidat)'
|
||||
: ''}
|
||||
{row.durationLabel ? ` | ${row.durationLabel}` : ''}
|
||||
{row.audioTrackCount > 0 ? ` | Audio: ${row.audioTrackCount}` : ''}
|
||||
{row.subtitleTrackCount > 0 ? ` | Untertitel: ${row.subtitleTrackCount}` : ''}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Column } from 'primereact/column';
|
||||
import { Tag } from 'primereact/tag';
|
||||
import { Button } from 'primereact/button';
|
||||
import { Toast } from 'primereact/toast';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { api } from '../api/client';
|
||||
import { confirmModal } from '../utils/confirmModal';
|
||||
|
||||
@@ -26,6 +27,7 @@ function formatDetectedMediaType(value) {
|
||||
}
|
||||
|
||||
export default function DatabasePage() {
|
||||
const navigate = useNavigate();
|
||||
const [orphanRows, setOrphanRows] = useState([]);
|
||||
const [orphanLoading, setOrphanLoading] = useState(false);
|
||||
const [orphanImportBusyPath, setOrphanImportBusyPath] = useState(null);
|
||||
@@ -63,13 +65,21 @@ export default function DatabasePage() {
|
||||
try {
|
||||
const response = await api.importOrphanRawFolder(row.rawPath);
|
||||
const newJobId = response?.job?.id;
|
||||
const activationStarted = Boolean(response?.activation?.started);
|
||||
toastRef.current?.show({
|
||||
severity: 'success',
|
||||
summary: 'Job angelegt',
|
||||
detail: newJobId ? `Historieneintrag #${newJobId} erstellt.` : 'Historieneintrag wurde erstellt.',
|
||||
summary: activationStarted ? 'Analyse gestartet' : 'Job angelegt',
|
||||
detail: activationStarted
|
||||
? (newJobId
|
||||
? `Job #${newJobId} läuft jetzt im Ripper-View.`
|
||||
: 'Job läuft jetzt im Ripper-View.')
|
||||
: (newJobId ? `Historieneintrag #${newJobId} erstellt.` : 'Historieneintrag wurde erstellt.'),
|
||||
life: 3500
|
||||
});
|
||||
await loadOrphans();
|
||||
if (activationStarted) {
|
||||
navigate('/ripper');
|
||||
}
|
||||
} catch (error) {
|
||||
toastRef.current?.show({
|
||||
severity: 'error',
|
||||
|
||||
Reference in New Issue
Block a user