Add FunClip timeline handoff source
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
@@ -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({
|
||||||
|
|||||||
Reference in New Issue
Block a user