fix(invite): the header Invite dialog's QR was still fetched from api.qrserver.com — render it locally (#192)

a899d7d3 moved the Room Settings share QR to qrcode.react but the
InviteUserPrompt (header ⋮ → Invite, Room Intro, space menu) kept the
third-party <img>, which leaked the room link and — since the prod CSP
img-src no longer allows that host — rendered as a broken image. Same
QRCodeSVG + white quiet zone as RoomShareInvite. Verified with
Playwright: SVG present, no remote <img>, zero external requests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
2026-09-18 00:47:37 -04:00
co-authored by Claude Opus 5
parent f528e5e440
commit 9d84f9153a
@@ -33,6 +33,7 @@ import {
import { Room } from 'matrix-js-sdk';
import { isKeyHotkey } from 'is-hotkey';
import FocusTrap from 'focus-trap-react';
import { QRCodeSVG } from 'qrcode.react';
import { stopPropagation } from '../../utils/keyboard';
import { useDirectUsers } from '../../hooks/useDirectUsers';
import {
@@ -237,13 +238,25 @@ export function InviteUserPrompt({ room, requestClose }: InviteUserProps) {
borderBottom: `1px solid ${color.Surface.ContainerLine}`,
}}
>
<img
src={`https://api.qrserver.com/v1/create-qr-code/?size=180x180&data=${encodeURIComponent(inviteUrl)}`}
alt="QR code for room invite link"
width={180}
height={180}
style={{ display: 'block', borderRadius: config.radii.R300 }}
/>
{/* Generated locally (qrcode.react) like RoomShareInvite — the
old api.qrserver.com <img> leaked the room link to a third
party and is blocked by the prod CSP img-src anyway
(Gitea #192). White quiet-zone so it scans on any theme. */}
<Box
style={{
padding: config.space.S200,
background: '#ffffff',
borderRadius: config.radii.R300,
lineHeight: 0,
}}
>
<QRCodeSVG
value={inviteUrl}
size={164}
level="M"
title="QR code for room invite link"
/>
</Box>
<Text
size="T200"
style={{ opacity: 0.6, wordBreak: 'break-all', textAlign: 'center' }}