perf(canvas): 画布媒体 - 优化媒体加载、播放器与节点交互 (#357)

Merge origin/main at fb089b2 and retain canvas media performance, player layout, and interaction updates.

Co-authored-by: ddCat <2695092045@qq.com>
This commit is contained in:
wurendao007
2026-08-31 09:00:37 +08:00
committed by GitHub
parent 21facff923
commit 8ebceecbb6
58 changed files with 2662 additions and 207 deletions

View File

@@ -4,6 +4,7 @@ import { AudioLines, BookOpenText, Clock3, FileText, Image, Pencil, Search, Vide
import { WorkspaceState } from "@/components/layout/workspace-state";
import { canvasNodeMaterialSummary, canvasNodeSearchContext, canvasNodeSearchTimes, searchCanvasNodes } from "@/lib/canvas/canvas-node-search";
import { canvasNodeVideoPreviewUrl } from "@/lib/canvas/canvas-media-preview";
import { getNodeListLabel } from "@/lib/canvas/node-registry";
import { CanvasNodeType, type CanvasNodeData } from "@/types/canvas";
@@ -124,16 +125,13 @@ const CanvasNodeSearchResult = memo(function CanvasNodeSearchResult({ node, acti
function CanvasNodeSearchThumbnail({ node }: { node: CanvasNodeData }) {
const [failed, setFailed] = useState(false);
const mediaSource = node.metadata?.drawingPreviewUrl
const mediaSource = node.type === CanvasNodeType.Video ? canvasNodeVideoPreviewUrl(node) : node.metadata?.drawingPreviewUrl
|| node.metadata?.characterCoverUrl
|| node.metadata?.folder?.themeCover
|| ((node.type === CanvasNodeType.Image || node.type === CanvasNodeType.Video || node.type === CanvasNodeType.Panorama || node.type === CanvasNodeType.ColorGrade) ? node.metadata?.content : undefined);
|| ((node.type === CanvasNodeType.Image || node.type === CanvasNodeType.Panorama || node.type === CanvasNodeType.ColorGrade) ? node.metadata?.content : undefined);
const commonClass = "h-11 w-16 rounded-[var(--r-sm)] border object-cover";
const commonStyle = { borderColor: "color-mix(in srgb, var(--foreground) 9%, transparent)", background: "color-mix(in srgb, var(--foreground) 5%, transparent)" };
if (mediaSource && !failed && node.type === CanvasNodeType.Video) {
return <video src={mediaSource} muted playsInline preload="metadata" aria-label={`${node.title} 视频缩略图`} className={commonClass} style={commonStyle} onError={() => setFailed(true)} />;
}
if (mediaSource && !failed) {
return <img src={mediaSource} alt="" width={64} height={44} loading="lazy" decoding="async" className={commonClass} style={commonStyle} onError={() => setFailed(true)} />;
}