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:
1 parent
21facff923
commit
8ebceecbb6
58 files changed
+2662
-207
No files matched your search
@@ -481,14 +481,21 @@ function createInlineMentionChip(reference: CanvasResourceReference, token: stri
|
||||
|
||||
function createInlinePreview(reference: CanvasResourceReference) {
|
||||
if ((reference.kind === "image" || reference.kind === "video" || reference.kind === "character") && reference.previewUrl) {
|
||||
const media = document.createElement(reference.kind === "video" ? "video" : "img");
|
||||
const media = document.createElement("img");
|
||||
media.className = `canvas-resource-inline-preview is-${reference.kind}`;
|
||||
media.setAttribute("src", reference.previewUrl);
|
||||
media.setAttribute("alt", "");
|
||||
if (media instanceof HTMLVideoElement) {
|
||||
media.muted = true;
|
||||
media.preload = "metadata";
|
||||
}
|
||||
return media;
|
||||
}
|
||||
if (reference.kind === "video" && reference.mediaUrl) {
|
||||
const media = document.createElement("video");
|
||||
media.className = "canvas-resource-inline-preview is-video";
|
||||
media.setAttribute("src", reference.mediaUrl);
|
||||
media.setAttribute("aria-hidden", "true");
|
||||
media.muted = true;
|
||||
media.playsInline = true;
|
||||
media.preload = "metadata";
|
||||
media.onloadedmetadata = () => primeVideoPreviewFrame(media);
|
||||
return media;
|
||||
}
|
||||
const fallback = document.createElement("span");
|
||||
@@ -685,7 +692,10 @@ function MentionReferenceList({ references, activeReferenceId, onSelect }: { ref
|
||||
|
||||
function ReferencePreview({ reference }: { reference: CanvasResourceReference }) {
|
||||
if (reference.kind === "image" && reference.previewUrl) return <img src={reference.previewUrl} alt="" className="canvas-resource-mention-preview is-image" />;
|
||||
if (reference.kind === "video" && reference.previewUrl) return <video src={reference.previewUrl} className="canvas-resource-mention-preview is-video" muted preload="metadata" />;
|
||||
if (reference.kind === "video" && reference.previewUrl) return <img src={reference.previewUrl} alt="" className="canvas-resource-mention-preview is-video" loading="lazy" decoding="async" />;
|
||||
if (reference.kind === "video" && reference.mediaUrl) {
|
||||
return <video src={reference.mediaUrl} aria-hidden="true" muted playsInline preload="metadata" className="canvas-resource-mention-preview is-video" onLoadedMetadata={(event) => primeVideoPreviewFrame(event.currentTarget)} />;
|
||||
}
|
||||
if (reference.kind === "character" && reference.previewUrl) return <img src={reference.previewUrl} alt="" className="canvas-resource-mention-preview is-character" />;
|
||||
if (reference.kind === "skill") {
|
||||
return (
|
||||
@@ -702,6 +712,17 @@ function ReferencePreview({ reference }: { reference: CanvasResourceReference })
|
||||
);
|
||||
}
|
||||
|
||||
function primeVideoPreviewFrame(video: HTMLVideoElement) {
|
||||
if (video.currentTime !== 0 || !Number.isFinite(video.duration) || video.duration <= 0) return;
|
||||
try {
|
||||
// Metadata-only loading does not paint a frame consistently across browsers.
|
||||
// Seeking a tiny amount keeps this preview passive while forcing first-frame decode.
|
||||
video.currentTime = Math.min(0.001, video.duration);
|
||||
} catch {
|
||||
// A transient media error should leave the fallback element usable.
|
||||
}
|
||||
}
|
||||
|
||||
function splitMentionText(value: string, references: CanvasResourceReference[]) {
|
||||
if (!references.length || !value) return value ? [{ type: "text", text: value } as MentionTextPart] : [];
|
||||
const referenceByToken = new Map<string, { reference: CanvasResourceReference; serializedToken: string }>();
|
||||
|
||||
Reference in new issue
Block a user