Revert to version 990839e
This commit is contained in:
parent
5d79b82de2
commit
5e2bccdca0
@ -392,18 +392,7 @@ const resolveDurationWithFallback = async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const requestUrl =
|
const response = await axios.get(playbackUrl, { responseType: 'blob' });
|
||||||
playbackUrl.startsWith('http://') || playbackUrl.startsWith('https://')
|
|
||||||
? playbackUrl
|
|
||||||
: playbackUrl.replace(/^\/api(?=\/)/, '');
|
|
||||||
|
|
||||||
const token =
|
|
||||||
typeof window !== 'undefined' ? localStorage.getItem('token') || '' : '';
|
|
||||||
const response = await axios.get(requestUrl, {
|
|
||||||
responseType: 'blob',
|
|
||||||
headers: token ? { Authorization: `Bearer ${token}` } : undefined,
|
|
||||||
});
|
|
||||||
|
|
||||||
const blobUrl = URL.createObjectURL(response.data);
|
const blobUrl = URL.createObjectURL(response.data);
|
||||||
try {
|
try {
|
||||||
const blobDuration = await readMediaDuration(blobUrl, mediaType);
|
const blobDuration = await readMediaDuration(blobUrl, mediaType);
|
||||||
@ -549,6 +538,7 @@ const createDefaultElement = (
|
|||||||
navType: getNavigationButtonKind(type),
|
navType: getNavigationButtonKind(type),
|
||||||
iconUrl: '',
|
iconUrl: '',
|
||||||
transitionReverseMode: 'auto_reverse',
|
transitionReverseMode: 'auto_reverse',
|
||||||
|
transitionDurationSec: 0.7,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -749,7 +739,6 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
useState<EditorMenuItem>('none');
|
useState<EditorMenuItem>('none');
|
||||||
const [transitionPreview, setTransitionPreview] =
|
const [transitionPreview, setTransitionPreview] =
|
||||||
useState<TransitionPreviewState | null>(null);
|
useState<TransitionPreviewState | null>(null);
|
||||||
const [pendingNavigationPageId, setPendingNavigationPageId] = useState('');
|
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const [isSaving, setIsSaving] = useState(false);
|
const [isSaving, setIsSaving] = useState(false);
|
||||||
@ -759,6 +748,7 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
const [newTransitionVideoUrl, setNewTransitionVideoUrl] = useState('');
|
const [newTransitionVideoUrl, setNewTransitionVideoUrl] = useState('');
|
||||||
const [newTransitionSupportsReverse, setNewTransitionSupportsReverse] =
|
const [newTransitionSupportsReverse, setNewTransitionSupportsReverse] =
|
||||||
useState(true);
|
useState(true);
|
||||||
|
const [newTransitionDurationSec, setNewTransitionDurationSec] = useState(0.7);
|
||||||
const [errorMessage, setErrorMessage] = useState('');
|
const [errorMessage, setErrorMessage] = useState('');
|
||||||
const [successMessage, setSuccessMessage] = useState('');
|
const [successMessage, setSuccessMessage] = useState('');
|
||||||
const [resolvedDurationBySource, setResolvedDurationBySource] = useState<
|
const [resolvedDurationBySource, setResolvedDurationBySource] = useState<
|
||||||
@ -994,28 +984,8 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newTransitionVideoUrl) {
|
|
||||||
targets.push({ source: newTransitionVideoUrl, mediaType: 'video' });
|
|
||||||
}
|
|
||||||
|
|
||||||
elements.forEach((element) => {
|
|
||||||
if (!isNavigationElementType(element.type)) return;
|
|
||||||
if (element.transitionVideoUrl) {
|
|
||||||
targets.push({ source: element.transitionVideoUrl, mediaType: 'video' });
|
|
||||||
}
|
|
||||||
if (element.reverseVideoUrl) {
|
|
||||||
targets.push({ source: element.reverseVideoUrl, mediaType: 'video' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return targets;
|
return targets;
|
||||||
}, [
|
}, [backgroundAudioUrl, backgroundVideoUrl, selectedElement]);
|
||||||
backgroundAudioUrl,
|
|
||||||
backgroundVideoUrl,
|
|
||||||
elements,
|
|
||||||
newTransitionVideoUrl,
|
|
||||||
selectedElement,
|
|
||||||
]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let isCancelled = false;
|
let isCancelled = false;
|
||||||
@ -1080,19 +1050,6 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
getKnownDurationForSource(selectedElement.mediaUrl || ''),
|
getKnownDurationForSource(selectedElement.mediaUrl || ''),
|
||||||
);
|
);
|
||||||
}, [getKnownDurationForSource, selectedElement]);
|
}, [getKnownDurationForSource, selectedElement]);
|
||||||
const newTransitionDurationNote = useMemo(
|
|
||||||
() => formatDurationNote(getKnownDurationForSource(newTransitionVideoUrl)),
|
|
||||||
[getKnownDurationForSource, newTransitionVideoUrl],
|
|
||||||
);
|
|
||||||
const selectedTransitionDurationNote = useMemo(() => {
|
|
||||||
if (!selectedElement || !isNavigationElementType(selectedElement.type)) {
|
|
||||||
return 'Duration: unknown';
|
|
||||||
}
|
|
||||||
|
|
||||||
return formatDurationNote(
|
|
||||||
getKnownDurationForSource(selectedElement.transitionVideoUrl || ''),
|
|
||||||
);
|
|
||||||
}, [getKnownDurationForSource, selectedElement]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (newTransitionVideoUrl) return;
|
if (newTransitionVideoUrl) return;
|
||||||
@ -1100,32 +1057,6 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
setNewTransitionVideoUrl(transitionVideoAssetOptions[0].value);
|
setNewTransitionVideoUrl(transitionVideoAssetOptions[0].value);
|
||||||
}, [newTransitionVideoUrl, transitionVideoAssetOptions]);
|
}, [newTransitionVideoUrl, transitionVideoAssetOptions]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setElements((prev) => {
|
|
||||||
let hasChanges = false;
|
|
||||||
const next = prev.map((element) => {
|
|
||||||
if (!isNavigationElementType(element.type)) return element;
|
|
||||||
|
|
||||||
const resolvedDuration = getKnownDurationForSource(
|
|
||||||
element.transitionVideoUrl || '',
|
|
||||||
);
|
|
||||||
const nextDuration =
|
|
||||||
Number.isFinite(resolvedDuration) && Number(resolvedDuration) > 0
|
|
||||||
? Number(resolvedDuration)
|
|
||||||
: undefined;
|
|
||||||
if (element.transitionDurationSec === nextDuration) return element;
|
|
||||||
|
|
||||||
hasChanges = true;
|
|
||||||
return {
|
|
||||||
...element,
|
|
||||||
transitionDurationSec: nextDuration,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return hasChanges ? next : prev;
|
|
||||||
});
|
|
||||||
}, [getKnownDurationForSource]);
|
|
||||||
|
|
||||||
const loadData = useCallback(async () => {
|
const loadData = useCallback(async () => {
|
||||||
if (!projectId || !router.isReady || !isAuthReady) return;
|
if (!projectId || !router.isReady || !isAuthReady) return;
|
||||||
|
|
||||||
@ -1712,13 +1643,7 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
const sanitizedName =
|
const sanitizedName =
|
||||||
String(newTransitionName || '').trim() ||
|
String(newTransitionName || '').trim() ||
|
||||||
`Transition ${Date.now().toString().slice(-4)}`;
|
`Transition ${Date.now().toString().slice(-4)}`;
|
||||||
const resolvedDurationSec = getKnownDurationForSource(sanitizedVideoUrl);
|
const parsedDuration = Number(newTransitionDurationSec);
|
||||||
if (!resolvedDurationSec) {
|
|
||||||
setErrorMessage(
|
|
||||||
'Could not resolve transition video duration yet. Please wait a moment and try again.',
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setIsCreatingTransition(true);
|
setIsCreatingTransition(true);
|
||||||
@ -1734,7 +1659,10 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
video_url: sanitizedVideoUrl,
|
video_url: sanitizedVideoUrl,
|
||||||
audio_url: '',
|
audio_url: '',
|
||||||
supports_reverse: Boolean(newTransitionSupportsReverse),
|
supports_reverse: Boolean(newTransitionSupportsReverse),
|
||||||
duration_sec: resolvedDurationSec,
|
duration_sec:
|
||||||
|
Number.isFinite(parsedDuration) && parsedDuration > 0
|
||||||
|
? parsedDuration
|
||||||
|
: 0.7,
|
||||||
};
|
};
|
||||||
|
|
||||||
await axios.post('/transitions', { data: payload });
|
await axios.post('/transitions', { data: payload });
|
||||||
@ -1752,7 +1680,7 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
activePage?.environment,
|
activePage?.environment,
|
||||||
getKnownDurationForSource,
|
newTransitionDurationSec,
|
||||||
newTransitionName,
|
newTransitionName,
|
||||||
newTransitionSupportsReverse,
|
newTransitionSupportsReverse,
|
||||||
newTransitionVideoUrl,
|
newTransitionVideoUrl,
|
||||||
@ -1996,44 +1924,6 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
element.navType === 'back' || element.type === 'navigation_prev'
|
element.navType === 'back' || element.type === 'navigation_prev'
|
||||||
? 'back'
|
? 'back'
|
||||||
: 'forward';
|
: 'forward';
|
||||||
const configuredTargetId = String(element.targetPageId || '').trim();
|
|
||||||
const fallbackTargetId = (() => {
|
|
||||||
const currentPageIndex = pages.findIndex(
|
|
||||||
(page) => page.id === activePageId,
|
|
||||||
);
|
|
||||||
if (currentPageIndex < 0) return '';
|
|
||||||
|
|
||||||
const nextPageIndex =
|
|
||||||
direction === 'back' ? currentPageIndex - 1 : currentPageIndex + 1;
|
|
||||||
const nextPage = pages[nextPageIndex];
|
|
||||||
return nextPage ? String(nextPage.id || '').trim() : '';
|
|
||||||
})();
|
|
||||||
const targetPageId = configuredTargetId || fallbackTargetId;
|
|
||||||
|
|
||||||
if (!targetPageId) {
|
|
||||||
setErrorMessage('No target page available for this navigation button.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const hasPlayableTransition =
|
|
||||||
Boolean(element.transitionVideoUrl) &&
|
|
||||||
!(
|
|
||||||
direction === 'back' &&
|
|
||||||
element.transitionReverseMode === 'separate_video' &&
|
|
||||||
!element.reverseVideoUrl
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!hasPlayableTransition) {
|
|
||||||
setPendingNavigationPageId('');
|
|
||||||
setTransitionPreview(null);
|
|
||||||
setActivePageId(targetPageId);
|
|
||||||
setSelectedElementId('');
|
|
||||||
setSelectedMenuItem('none');
|
|
||||||
setErrorMessage('');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setPendingNavigationPageId(targetPageId);
|
|
||||||
openTransitionPreviewForElement(element, direction);
|
openTransitionPreviewForElement(element, direction);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -2376,16 +2266,6 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
const finishPreview = () => {
|
const finishPreview = () => {
|
||||||
cleanupReverseFrame();
|
cleanupReverseFrame();
|
||||||
setTransitionPreview(null);
|
setTransitionPreview(null);
|
||||||
setPendingNavigationPageId((pendingPageId) => {
|
|
||||||
const nextPageId = String(pendingPageId || '').trim();
|
|
||||||
if (nextPageId) {
|
|
||||||
setActivePageId(nextPageId);
|
|
||||||
setSelectedElementId('');
|
|
||||||
setSelectedMenuItem('none');
|
|
||||||
setErrorMessage('');
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const configuredDurationMs =
|
const configuredDurationMs =
|
||||||
@ -2820,10 +2700,6 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
<p className='text-[11px] text-gray-500'>
|
|
||||||
Transition duration is automatic from video metadata.{' '}
|
|
||||||
{newTransitionDurationNote}
|
|
||||||
</p>
|
|
||||||
<label className='flex items-center gap-2 text-[11px] text-gray-700'>
|
<label className='flex items-center gap-2 text-[11px] text-gray-700'>
|
||||||
<input
|
<input
|
||||||
type='checkbox'
|
type='checkbox'
|
||||||
@ -2834,6 +2710,18 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
/>
|
/>
|
||||||
Supports reverse playback
|
Supports reverse playback
|
||||||
</label>
|
</label>
|
||||||
|
<input
|
||||||
|
className='w-full rounded border border-gray-300 px-2 py-1 text-xs'
|
||||||
|
type='number'
|
||||||
|
min='0.2'
|
||||||
|
step='0.1'
|
||||||
|
value={newTransitionDurationSec}
|
||||||
|
onChange={(event) =>
|
||||||
|
setNewTransitionDurationSec(
|
||||||
|
Number(event.target.value || 0.7),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
<button
|
<button
|
||||||
type='button'
|
type='button'
|
||||||
className='menu-action-btn'
|
className='menu-action-btn'
|
||||||
@ -3000,9 +2888,6 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
<p className='mt-1 text-[11px] text-gray-500'>
|
|
||||||
{selectedMediaDurationNote}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className='mb-1 block text-[11px] font-semibold text-gray-600'>
|
<label className='mb-1 block text-[11px] font-semibold text-gray-600'>
|
||||||
@ -3034,15 +2919,11 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
<select
|
<select
|
||||||
className='w-full rounded border border-gray-300 px-2 py-1 text-xs'
|
className='w-full rounded border border-gray-300 px-2 py-1 text-xs'
|
||||||
value={selectedElement.transitionVideoUrl || ''}
|
value={selectedElement.transitionVideoUrl || ''}
|
||||||
onChange={(event) => {
|
onChange={(event) =>
|
||||||
const nextVideoUrl = event.target.value;
|
|
||||||
const resolvedDuration =
|
|
||||||
getKnownDurationForSource(nextVideoUrl);
|
|
||||||
updateSelectedElement({
|
updateSelectedElement({
|
||||||
transitionVideoUrl: nextVideoUrl,
|
transitionVideoUrl: event.target.value,
|
||||||
transitionDurationSec: resolvedDuration || undefined,
|
})
|
||||||
});
|
}
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<option value=''>Not selected</option>
|
<option value=''>Not selected</option>
|
||||||
{addFallbackAssetOption(
|
{addFallbackAssetOption(
|
||||||
@ -3056,7 +2937,7 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
<p className='mt-1 text-[11px] text-gray-500'>
|
<p className='mt-1 text-[11px] text-gray-500'>
|
||||||
{selectedTransitionDurationNote}
|
{selectedMediaDurationNote}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@ -3114,10 +2995,25 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<p className='text-[11px] text-gray-500'>
|
<div>
|
||||||
Transition duration is set automatically from the selected
|
<label className='mb-1 block text-[11px] font-semibold text-gray-600'>
|
||||||
video. {selectedTransitionDurationNote}
|
Transition duration (sec)
|
||||||
</p>
|
</label>
|
||||||
|
<input
|
||||||
|
className='w-full rounded border border-gray-300 px-2 py-1 text-xs'
|
||||||
|
type='number'
|
||||||
|
min='0.2'
|
||||||
|
step='0.1'
|
||||||
|
value={selectedElement.transitionDurationSec ?? 0.7}
|
||||||
|
onChange={(event) =>
|
||||||
|
updateSelectedElement({
|
||||||
|
transitionDurationSec: Number(
|
||||||
|
event.target.value || 0.7,
|
||||||
|
),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div className='flex gap-2 pt-1'>
|
<div className='flex gap-2 pt-1'>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
small
|
small
|
||||||
@ -3688,19 +3584,7 @@ const ConstructorPage = ({ mode = 'constructor' }: ConstructorPageProps) => {
|
|||||||
<button
|
<button
|
||||||
type='button'
|
type='button'
|
||||||
className='absolute top-4 right-4 rounded bg-white/20 px-3 py-1 text-xs text-white hover:bg-white/30'
|
className='absolute top-4 right-4 rounded bg-white/20 px-3 py-1 text-xs text-white hover:bg-white/30'
|
||||||
onClick={() => {
|
onClick={() => setTransitionPreview(null)}
|
||||||
setTransitionPreview(null);
|
|
||||||
setPendingNavigationPageId((pendingPageId) => {
|
|
||||||
const nextPageId = String(pendingPageId || '').trim();
|
|
||||||
if (nextPageId) {
|
|
||||||
setActivePageId(nextPageId);
|
|
||||||
setSelectedElementId('');
|
|
||||||
setSelectedMenuItem('none');
|
|
||||||
setErrorMessage('');
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Close
|
Close
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user