Add FunClip timeline handoff source

This commit is contained in:
2026-07-07 09:39:54 +08:00
parent 13f44a4bbc
commit 38bba0828c
2 changed files with 45 additions and 7 deletions

View File

@@ -9780,6 +9780,37 @@ function FunClipEditingPage({
| 'clip' | 'clip'
| 'published'; | 'published';
const timelineHandoffSource = useMemo<ClipSource | null>(() => {
const asset = timelineHandoff?.asset;
const url = publishableAssetMediaUrl(asset);
if (!asset || (asset.type !== 'video' && asset.type !== 'audio') || !url) {
return null;
}
return {
id: `handoff-${asset.assetId || asset.id || 'media'}`,
assetId: asset.assetId || asset.id,
name: asset.name || '数字人成片',
type: asset.type,
source: 'asset-center',
section: 'work',
tags: Array.from(
new Set<AssetCenterSourceTag>([
...(asset.sourceTags || []),
'ai',
'clip',
])
),
provider: asset.provider || '数字人',
url,
thumbnailUrl: publishableAssetThumbnailUrl(asset),
localPath: asset.localPath,
durationMs: asset.durationMs,
width: asset.width,
height: asset.height,
createdAt: asset.createdAt || timelineHandoff.createdAt || Date.now(),
};
}, [timelineHandoff]);
const sourceOptions = useMemo<ClipSource[]>(() => { const sourceOptions = useMemo<ClipSource[]>(() => {
const materialSources = assets const materialSources = assets
.filter((asset) => asset.type === 'video' || asset.type === 'audio') .filter((asset) => asset.type === 'video' || asset.type === 'audio')
@@ -9830,7 +9861,11 @@ function FunClipEditingPage({
}; };
}); });
const seen = new Set<string>(); const seen = new Set<string>();
return [...finishedSources, ...materialSources] return [
...(timelineHandoffSource ? [timelineHandoffSource] : []),
...finishedSources,
...materialSources,
]
.filter((item) => { .filter((item) => {
const key = item.assetId || item.localPath || item.url || item.id; const key = item.assetId || item.localPath || item.url || item.id;
if (seen.has(key)) { if (seen.has(key)) {
@@ -9840,7 +9875,7 @@ function FunClipEditingPage({
return true; return true;
}) })
.sort((a, b) => b.createdAt - a.createdAt); .sort((a, b) => b.createdAt - a.createdAt);
}, [assets, finishedAssets]); }, [assets, finishedAssets, timelineHandoffSource]);
const clipPresets: Array<{ const clipPresets: Array<{
id: ClipPresetId; id: ClipPresetId;

View File

@@ -76,9 +76,7 @@ const ModelDescFallback: React.FC<{ model: ModelConfig }> = React.memo(
({ model }) => { ({ model }) => {
const meta = useModelMeta(model.sourceProfileId, model.id); const meta = useModelMeta(model.sourceProfileId, model.id);
if (!meta?.description) return null; if (!meta?.description) return null;
return ( return <div className="model-selector__item-desc">{meta.description}</div>;
<div className="model-selector__item-desc">{meta.description}</div>
);
} }
); );
@@ -209,7 +207,9 @@ export const ModelSelector: React.FC<ModelSelectorProps> = React.memo(
selectedModel, selectedModel,
selectedModelRef selectedModelRef
); );
setActiveVendor(selectedIsSelectable ? currentModel?.vendor || null : null); setActiveVendor(
selectedIsSelectable ? currentModel?.vendor || null : null
);
} else { } else {
setSearchQuery(''); setSearchQuery('');
} }
@@ -298,7 +298,10 @@ export const ModelSelector: React.FC<ModelSelectorProps> = React.memo(
const alignedLeft = rect.left; const alignedLeft = rect.left;
const nextLeft = Math.min( const nextLeft = Math.min(
Math.max(viewportGutter, alignedLeft), Math.max(viewportGutter, alignedLeft),
Math.max(viewportGutter, windowWidth - preferredWidth - viewportGutter) Math.max(
viewportGutter,
windowWidth - preferredWidth - viewportGutter
)
); );
setPortalPosition({ setPortalPosition({