feat: QR code in invite modal; fix CSP to allow api.qrserver.com

InviteUserPrompt: add QR code toggle button (Icons.BlockCode) in header.
When toggled, shows a 180x180 QR code image (api.qrserver.com) and the
raw invite URL below it, between the header and the search form.
inviteUrl computed once and shared between Copy Link and QR display.

Server: added https://api.qrserver.com to img-src in CSP header on
LXC 106 (/etc/nginx/sites-available/cinny) — nginx reloaded.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-03 10:10:25 -04:00
parent da35278b30
commit 906884e434
@@ -68,11 +68,16 @@ export function InviteUserPrompt({ room, requestClose }: InviteUserProps) {
const mx = useMatrixClient();
const alive = useAlive();
const [linkCopied, setLinkCopied] = useState(false);
const [showQr, setShowQr] = useState(false);
const handleCopyLink = () => {
const inviteUrl = (() => {
const roomIdOrAlias = getCanonicalAliasOrRoomId(mx, room.roomId);
const viaServers = isRoomAlias(roomIdOrAlias) ? undefined : getViaServers(room);
copyToClipboard(getMatrixToRoom(roomIdOrAlias, viaServers));
return getMatrixToRoom(roomIdOrAlias, viaServers);
})();
const handleCopyLink = () => {
copyToClipboard(inviteUrl);
setLinkCopied(true);
setTimeout(() => setLinkCopied(false), 2000);
};
@@ -202,11 +207,47 @@ export function InviteUserPrompt({ room, requestClose }: InviteUserProps) {
>
<Text size="B300">{linkCopied ? 'Copied!' : 'Copy Link'}</Text>
</Button>
<IconButton
size="300"
radii="300"
variant={showQr ? 'Primary' : 'Surface'}
fill={showQr ? 'Soft' : 'None'}
aria-label="Show QR code"
aria-pressed={showQr}
onClick={() => setShowQr((v) => !v)}
>
<Icon src={Icons.BlockCode} size="100" />
</IconButton>
<IconButton size="300" radii="300" onClick={requestClose} aria-label="Close">
<Icon src={Icons.Cross} />
</IconButton>
</Box>
</Header>
{showQr && (
<Box
direction="Column"
alignItems="Center"
gap="200"
style={{
padding: config.space.S300,
borderBottom: `1px solid var(--bg-surface-border)`,
}}
>
<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 }}
/>
<Text
size="T200"
style={{ opacity: 0.6, wordBreak: 'break-all', textAlign: 'center' }}
>
{inviteUrl}
</Text>
</Box>
)}
<Box
as="form"
onSubmit={handleSubmit}