feat: QR code in invite modal; fix CSP to allow api.qrserver.com
CI / Build & Quality Checks (push) Successful in 10m30s

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 69249d1746
commit 4af07109c3
@@ -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}