fix(url-preview): thumbnail fallback + quiet timeline console spam
Two console-noise / glitch fixes surfaced while a room with link
previews was open:
- URL preview og:image thumbnails 400 when Synapse can't thumbnail a
cached preview image (SVG/animated), leaving a broken image that the
browser keeps re-requesting. GenericCard now falls back to the full
image on error, then hides the image (and shows the link icon) if that
also fails, so no broken image and no repeated failing requests.
- Extend the existing console.warn filter to drop matrix-js-sdk's
high-volume, benign timeline bookkeeping warnings ("EventTimelineSet…"
and "Decrypted event … is not in room …"), which fire constantly in
E2EE rooms with threads. Real warnings still log.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1965,16 +1965,29 @@ function GenericCard({
|
||||
const description = prev['og:description'] ?? '';
|
||||
const siteName = typeof prev['og:site_name'] === 'string' ? prev['og:site_name'] : undefined;
|
||||
|
||||
// Synapse returns 400 from the thumbnail endpoint when it can't thumbnail a
|
||||
// cached preview image (e.g. SVG/animated). Fall back to the full image, then
|
||||
// hide entirely if that also fails — otherwise the card shows a broken image
|
||||
// and the browser keeps re-requesting the failing thumbnail (console spam).
|
||||
const [useFullImg, setUseFullImg] = useState(false);
|
||||
const [imgFailed, setImgFailed] = useState(false);
|
||||
const displayThumb = useFullImg ? imgUrl : thumbUrl;
|
||||
const handleImgError = () => {
|
||||
if (!useFullImg && imgUrl && imgUrl !== thumbUrl) setUseFullImg(true);
|
||||
else setImgFailed(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{thumbUrl && (
|
||||
{!imgFailed && displayThumb && (
|
||||
<UrlPreviewImg
|
||||
src={thumbUrl}
|
||||
src={displayThumb}
|
||||
alt={prev['og:title']}
|
||||
title={prev['og:title']}
|
||||
tabIndex={0}
|
||||
onKeyDown={(evt) => onEnterOrSpace(() => onOpenViewer())(evt)}
|
||||
onClick={onOpenViewer}
|
||||
onError={handleImgError}
|
||||
/>
|
||||
)}
|
||||
{imgUrl && (
|
||||
@@ -1997,7 +2010,7 @@ function GenericCard({
|
||||
size="T200"
|
||||
priority="300"
|
||||
>
|
||||
{!thumbUrl && (
|
||||
{(!displayThumb || imgFailed) && (
|
||||
<Icon
|
||||
src={Icons.Link}
|
||||
size="50"
|
||||
|
||||
+16
-4
@@ -68,13 +68,25 @@ window.addEventListener('vite:preloadError', () => {
|
||||
// Clear the reload flag after a successful load so future deploys can still trigger a reload
|
||||
window.addEventListener('load', () => sessionStorage.removeItem('chunk-reload-attempted'));
|
||||
|
||||
// Synapse does not yet ship MSC3786/MSC3914 as server-default push rules.
|
||||
// matrix-js-sdk patches them client-side on every login and logs a warn for each.
|
||||
// Suppress the noise until Synapse implements these MSCs upstream.
|
||||
// Filter out known-benign, high-volume matrix-js-sdk console warnings that we
|
||||
// can't fix client-side and that would otherwise flood the console:
|
||||
// - "Adding default global …": the SDK patches MSC3786/MSC3914 push rules on
|
||||
// every login (one warn each) until Synapse ships them as server defaults.
|
||||
// - "EventTimelineSet…": the SDK loudly warns whenever a decrypted event
|
||||
// references a thread/room the current timeline set doesn't hold, then
|
||||
// discards it harmlessly. This fires constantly in E2EE rooms with threads.
|
||||
// - "Decrypted event … is not in room …": same family — a late decryption for
|
||||
// an event the room's timeline no longer tracks; ignored by the SDK.
|
||||
// These are informational SDK bookkeeping, not errors; real warnings still log.
|
||||
{
|
||||
const suppressedPrefixes = ['Adding default global ', 'EventTimelineSet'];
|
||||
const _warn = console.warn.bind(console);
|
||||
console.warn = (...args: unknown[]) => {
|
||||
if (typeof args[0] === 'string' && args[0].startsWith('Adding default global ')) return;
|
||||
const first = args[0];
|
||||
if (typeof first === 'string') {
|
||||
if (suppressedPrefixes.some((p) => first.startsWith(p))) return;
|
||||
if (first.startsWith('Decrypted event ') && first.includes('is not in room')) return;
|
||||
}
|
||||
_warn(...args);
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user