fix: media gallery thumbnails — skip auth URL, handle encrypted media
- Use useAuthentication=false for thumbnail requests: the v1 authenticated URL adds allow_redirect=true which Synapse rejects with 400 - Encrypted events (content.file set) show a lock+filename placeholder since server can't thumbnail encrypted blobs - Unencrypted thumbnails add onError handler to hide broken images gracefully Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -211,36 +211,65 @@ export function MediaGallery({ room, onClose }: MediaGalleryProps) {
|
||||
>
|
||||
{events.map((mEvent) => {
|
||||
const content = mEvent.getContent();
|
||||
const isEncrypted = !!content.file;
|
||||
const mxcUrl: string | undefined = content.url ?? content.file?.url;
|
||||
if (!mxcUrl) return null;
|
||||
const thumbUrl =
|
||||
mxcUrlToHttp(mx, mxcUrl, useAuthentication, 120, 120, 'crop') ?? '';
|
||||
const body: string = content.body ?? '';
|
||||
// Use unauthenticated thumbnail URL — the v1 authenticated endpoint adds
|
||||
// allow_redirect=true which Synapse rejects with 400.
|
||||
const thumbUrl = isEncrypted
|
||||
? null
|
||||
: (mxcUrlToHttp(mx, mxcUrl, false, 120, 120, 'crop') ?? null);
|
||||
const fullUrl = mxcUrlToHttp(mx, mxcUrl, useAuthentication) ?? '#';
|
||||
return (
|
||||
<a
|
||||
key={mEvent.getId()}
|
||||
href={mxcUrlToHttp(mx, mxcUrl, useAuthentication) ?? '#'}
|
||||
target="_blank"
|
||||
href={isEncrypted ? '#' : fullUrl}
|
||||
target={isEncrypted ? undefined : '_blank'}
|
||||
rel="noreferrer"
|
||||
style={{
|
||||
display: 'block',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
aspectRatio: '1',
|
||||
overflow: 'hidden',
|
||||
borderRadius: config.radii.R300,
|
||||
background: 'var(--bg-surface)',
|
||||
background: 'var(--bg-surface-low)',
|
||||
cursor: isEncrypted ? 'default' : 'pointer',
|
||||
}}
|
||||
title={body}
|
||||
>
|
||||
<img
|
||||
src={thumbUrl}
|
||||
alt={body}
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
objectFit: 'cover',
|
||||
display: 'block',
|
||||
}}
|
||||
/>
|
||||
{thumbUrl ? (
|
||||
<img
|
||||
src={thumbUrl}
|
||||
alt={body}
|
||||
onError={(e) => {
|
||||
(e.currentTarget as HTMLImageElement).style.display = 'none';
|
||||
}}
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
objectFit: 'cover',
|
||||
display: 'block',
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Box
|
||||
direction="Column"
|
||||
alignItems="Center"
|
||||
gap="100"
|
||||
style={{ padding: config.space.S100 }}
|
||||
>
|
||||
<Icon src={isEncrypted ? Icons.Lock : Icons.Photo} size="400" />
|
||||
<Text
|
||||
size="T200"
|
||||
truncate
|
||||
style={{ maxWidth: '100%', textAlign: 'center', opacity: 0.7 }}
|
||||
>
|
||||
{body || (isEncrypted ? 'Encrypted' : 'Image')}
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
|
||||
Reference in New Issue
Block a user