diff --git a/frontend/src/components/ui/VideoSplitModal.tsx b/frontend/src/components/ui/VideoSplitModal.tsx index 4733e31..53a4d80 100644 --- a/frontend/src/components/ui/VideoSplitModal.tsx +++ b/frontend/src/components/ui/VideoSplitModal.tsx @@ -10,8 +10,14 @@ import Checkbox from './Checkbox' import { LinkIcon } from '@heroicons/react/24/outline' import { getSegmentLabelText, - getHighestPrioritySegmentLabelItem, + getSegmentLabelItem, } from './Icons' +import { + isKnownFrontendPositionLabel, + normalizeAiLabel, + rawAiLabelParts, + segmentTitleFromLabel, +} from '../../aiLabels' import { formatDateTime } from './formatters' type Segment = { @@ -1028,11 +1034,37 @@ function segmentPairKey(aIndex: number, bIndex: number): string { return `${a}:${b}` } +// Höchstpriorisierter Roh-Label-Teil (Position > Objekt > Körper > Kleidung), +// damit Icon und Text genauso wie im RatingOverlay die Position bevorzugen +// statt z.B. "Vagina" aus einem Combo-Label zu ziehen. +function primaryIconLabelFromParts(parts: string[]): string { + if (parts.length === 0) return '' + if (parts.length === 1) return parts[0] + + return ( + parts.find((part) => ( + part.startsWith('position:') || + isKnownFrontendPositionLabel(normalizeAiLabel(part)) + )) ?? + parts.find((part) => part.startsWith('object:')) ?? + parts.find((part) => part.startsWith('body:')) ?? + parts.find((part) => part.startsWith('clothing:')) ?? + parts[0] + ) +} + +function groupPrimaryIconLabel(group: Segment[]): string { + const parts = group.flatMap((seg) => rawAiLabelParts(seg.label)) + return primaryIconLabelFromParts(parts) +} + function buildMergedSegmentLabel(group: Segment[]): string { + // segmentTitleFromLabel bevorzugt die Position (wie im RatingOverlay), + // statt über getSegmentLabelText auf das Körperteil zurückzufallen. const labels = Array.from( new Set( group - .map((seg) => getSegmentLabelText(seg.label).trim()) + .map((seg) => segmentTitleFromLabel(seg.label).trim()) .filter(Boolean) ) ) @@ -2063,8 +2095,8 @@ export default function VideoSplitModal({ const mergedLabel = buildMergedSegmentLabel(group.segments) const cleanLabel = mergedLabel - const topGroupLabelItem = getHighestPrioritySegmentLabelItem( - group.segments.map((seg) => seg.label) + const topGroupLabelItem = getSegmentLabelItem( + groupPrimaryIconLabel(group.segments) ) const showTextLabel = width >= 8 @@ -2410,8 +2442,8 @@ export default function VideoSplitModal({ isEnteringMerged && showEnteringMergedGroup && 'opacity-100 scale-100' ) - const topGroupLabelItem = getHighestPrioritySegmentLabelItem( - group.segments.map((seg) => seg.label) + const topGroupLabelItem = getSegmentLabelItem( + groupPrimaryIconLabel(group.segments) ) return (