Revert "chore(chat): trace the composer video poster lifecycle"

This reverts commit bda6633465.
This commit is contained in:
dolphin
2026-08-24 18:38:37 +08:00
parent 8e77d81cb9
commit f5a67e608f
3 changed files with 9 additions and 60 deletions
@@ -12,7 +12,6 @@ import {
getMediaKind,
isMediaAttachmentFile,
resolveMediaCoverUrl,
tracePoster,
resolveMediaPlaybackUrl,
type MediaParsingState,
} from '~/utils/mediaAttachmentUtils';
@@ -79,16 +78,6 @@ export function MediaAttachmentChip({
setCoverFailed(false);
}, [resolvedCoverUrl]);
const coverUrl = coverFailed ? undefined : resolvedCoverUrl;
if (kind === 'video') {
tracePoster('chip:render', {
name: fileName,
variant,
raw: rawCoverUrl?.slice(0, 24),
cover: coverUrl?.slice(0, 24),
coverFilepath: (file.cover_filepath ?? '').slice(0, 40),
failed: coverFailed,
});
}
const mediaFilepath = extractMediaFilepath(file);
const canPlay = !!playbackUrl && !isUploading;
const parsingLabel = localize('com_chat.media_parsing');
@@ -147,10 +136,7 @@ export function MediaAttachmentChip({
src={coverUrl}
alt=""
className="size-full object-cover"
onError={() => {
tracePoster('img:error', { name: fileName, cover: coverUrl?.slice(0, 60) });
setCoverFailed(true);
}}
onError={() => setCoverFailed(true)}
/>
) : (
<>
@@ -28,7 +28,6 @@ import {
import {
captureVideoPosterFromFile,
getMediaKind,
tracePoster,
readMediaDurationFromFile,
isMediaAttachmentFile,
} from "~/utils/mediaAttachmentUtils";
@@ -85,7 +84,6 @@ const applyParseStatusToFile = (file: any, entry: { parsing_status?: string; cov
...(coverFilepath ? { cover_filepath: coverFilepath } : {}),
};
if (coverFilepath && file.mediaCoverUrl?.startsWith('blob:')) {
tracePoster('revoke:parse-status', { id: file.id, coverFilepath });
URL.revokeObjectURL(file.mediaCoverUrl);
next.mediaCoverUrl = undefined;
}
@@ -311,15 +309,9 @@ const InputFiles = forwardRef(({ v, showVoice, accepts, disabled = false, size,
const target = filesRef.current.find((f) => f.id === id);
// Removed while decoding, or the server poster won the race.
if (!target || target.cover_filepath) {
tracePoster('apply:dropped', {
id,
reason: target ? 'server-cover' : 'file-gone',
ids: filesRef.current.map((f) => f.id),
});
URL.revokeObjectURL(mediaCoverUrl);
return;
}
tracePoster('apply:ok', { id, name: target.name });
const updated = filesRef.current.map((f) =>
f.id === id ? { ...f, mediaCoverUrl } : f,
);
@@ -400,7 +392,6 @@ const InputFiles = forwardRef(({ v, showVoice, accepts, disabled = false, size,
...(coverFilepath ? { cover_filepath: coverFilepath } : {}),
};
if (coverFilepath && f.mediaCoverUrl?.startsWith('blob:')) {
tracePoster('revoke:upload-response', { id, coverFilepath });
URL.revokeObjectURL(f.mediaCoverUrl);
next.mediaCoverUrl = undefined;
}
@@ -544,7 +535,6 @@ const InputFiles = forwardRef(({ v, showVoice, accepts, disabled = false, size,
},
supportsFolderUpload,
clear: () => {
tracePoster('clear', { ids: filesRef.current.map((f) => f.id) });
filesRef.current.forEach(f => {
if (f.previewUrl) URL.revokeObjectURL(f.previewUrl);
if (f.mediaPreviewUrl) URL.revokeObjectURL(f.mediaPreviewUrl);
@@ -560,7 +550,6 @@ const InputFiles = forwardRef(({ v, showVoice, accepts, disabled = false, size,
// Release any live object URLs when the component unmounts so pinned image
// previews don't leak blobs.
useEffect(() => () => {
tracePoster('unmount', { ids: filesRef.current.map((f) => f.id) });
filesRef.current.forEach(f => {
if (f.previewUrl) URL.revokeObjectURL(f.previewUrl);
if (f.mediaPreviewUrl) URL.revokeObjectURL(f.mediaPreviewUrl);
@@ -650,10 +639,7 @@ const InputFiles = forwardRef(({ v, showVoice, accepts, disabled = false, size,
}
if (removed?.previewUrl) URL.revokeObjectURL(removed.previewUrl);
if (removed?.mediaPreviewUrl) URL.revokeObjectURL(removed.mediaPreviewUrl);
if (removed?.mediaCoverUrl?.startsWith('blob:')) {
tracePoster('revoke:remove', { id: removed.id });
URL.revokeObjectURL(removed.mediaCoverUrl);
}
if (removed?.mediaCoverUrl?.startsWith('blob:')) URL.revokeObjectURL(removed.mediaCoverUrl);
const res = filesRef.current.filter(file => String(file.id) !== String(clientId));
filesRef.current = res
setFiles(res);
@@ -72,20 +72,6 @@ export function readMediaDurationFromFile(file: File): Promise<number | undefine
});
}
/** TEMPORARY diagnostic for the composer video poster (remove once the
* disappearing-thumbnail report is closed). Production builds strip console.*,
* so events land in a ring buffer instead: read `window.__posterTrace`. */
export function tracePoster(event: string, data?: Record<string, unknown>): void {
try {
const holder = window as unknown as { __posterTrace?: Record<string, unknown>[] };
if (!holder.__posterTrace) holder.__posterTrace = [];
holder.__posterTrace.push({ at: new Date().toISOString(), event, ...(data ?? {}) });
if (holder.__posterTrace.length > 300) holder.__posterTrace.shift();
} catch {
// Diagnostics must never break the upload flow.
}
}
/** How long to wait for the browser to decode a first frame before giving up.
* A codec it cannot handle usually errors out at once, but some containers just
* never fire an event — without this the promise would hang and leak the URL. */
@@ -101,19 +87,11 @@ export function captureVideoPosterFromFile(file: File): Promise<string | undefin
video.playsInline = true;
video.preload = 'auto';
const startedAt = Date.now();
tracePoster('capture:start', { name: file.name, size: file.size, type: file.type });
let settled = false;
const settle = (poster?: string, reason?: string) => {
const settle = (poster?: string) => {
if (settled) return;
settled = true;
window.clearTimeout(timeoutId);
tracePoster('capture:end', {
name: file.name,
ok: !!poster,
reason,
ms: Date.now() - startedAt,
});
resolve(poster);
};
@@ -125,11 +103,10 @@ export function captureVideoPosterFromFile(file: File): Promise<string | undefin
const timeoutId = window.setTimeout(() => {
cleanup();
settle(undefined, 'timeout');
settle(undefined);
}, VIDEO_POSTER_TIMEOUT_MS);
video.onloadeddata = () => {
tracePoster('capture:loadeddata', { name: file.name });
video.currentTime = 0.001;
};
video.onseeked = () => {
@@ -138,7 +115,7 @@ export function captureVideoPosterFromFile(file: File): Promise<string | undefin
const height = video.videoHeight;
if (!width || !height) {
cleanup();
settle(undefined, 'no-dimensions');
settle(undefined);
return;
}
const canvas = document.createElement('canvas');
@@ -147,7 +124,7 @@ export function captureVideoPosterFromFile(file: File): Promise<string | undefin
const ctx = canvas.getContext('2d');
if (!ctx) {
cleanup();
settle(undefined, 'no-2d-context');
settle(undefined);
return;
}
ctx.drawImage(video, 0, 0, width, height);
@@ -159,14 +136,14 @@ export function captureVideoPosterFromFile(file: File): Promise<string | undefin
'image/jpeg',
0.85,
);
} catch (err) {
} catch {
cleanup();
settle(undefined, `draw-threw:${String(err)}`);
settle(undefined);
}
};
video.onerror = () => {
cleanup();
settle(undefined, 'video-error');
settle(undefined);
};
video.src = url;
});