fuzzyworld

word-waltz / files / src / components / ShareDialog.ts

ShareDialog.ts

Blame: the commit that last changed each line · file · history

f755bca6 2026-03-23 Pavel Safronov1/**
2 * ShareDialog — shareable link + QR code UI
3 *
4 * Displays the game invite URL (with the encryption key in the fragment)
5 * and renders a QR code of that URL so the opponent can scan to join.
6 */
7
1c548168 2026-03-24 Pavel Safronov8import QRCode from 'qrcode';
9
f755bca6 2026-03-23 Pavel Safronov10interface ShareDialogProps {
11 shareUrl: string;
12}
13
14export function mountShareDialog(container: HTMLElement, props: ShareDialogProps): () => void {
1c548168 2026-03-24 Pavel Safronov15 const { shareUrl } = props;
16
17 const root = document.createElement('div');
18 root.className = 'share-dialog';
19
20 const canvas = document.createElement('canvas');
21 canvas.className = 'share-dialog__qr';
22
23 const linkEl = document.createElement('a');
24 linkEl.className = 'share-dialog__link';
25 linkEl.href = shareUrl;
26 linkEl.textContent = shareUrl;
27
28 const copyBtn = document.createElement('button');
29 copyBtn.className = 'share-dialog__copy';
30 copyBtn.type = 'button';
31 copyBtn.textContent = 'Copy link';
e86661e4 2026-03-24 Pavel Safronov32 let resetTimer: ReturnType<typeof setTimeout> | null = null;
1c548168 2026-03-24 Pavel Safronov33 copyBtn.addEventListener('click', () => {
e86661e4 2026-03-24 Pavel Safronov34 if (copyBtn.disabled) return;
35 copyBtn.disabled = true;
1c548168 2026-03-24 Pavel Safronov36 navigator.clipboard.writeText(shareUrl).then(() => {
37 copyBtn.textContent = 'Copied!';
e86661e4 2026-03-24 Pavel Safronov38 }).catch(() => {
39 copyBtn.textContent = 'Copy failed';
40 }).finally(() => {
41 if (resetTimer !== null) clearTimeout(resetTimer);
42 resetTimer = setTimeout(() => {
43 copyBtn.textContent = 'Copy link';
44 copyBtn.disabled = false;
45 }, 2000);
46 });
1c548168 2026-03-24 Pavel Safronov47 });
48
49 root.appendChild(canvas);
50 root.appendChild(linkEl);
51 root.appendChild(copyBtn);
52 container.appendChild(root);
53
54 QRCode.toCanvas(canvas, shareUrl, { width: 220, margin: 2 }).catch((err: unknown) => {
55 console.error('QR generation failed:', err);
e86661e4 2026-03-24 Pavel Safronov56 canvas.style.display = 'none';
57 const qrError = document.createElement('p');
58 qrError.className = 'share-dialog__qr-error';
59 qrError.textContent = 'QR code unavailable — copy the link below.';
60 root.insertBefore(qrError, linkEl);
1c548168 2026-03-24 Pavel Safronov61 });
62
63 return function cleanup() {
64 container.removeChild(root);
65 };
f755bca6 2026-03-23 Pavel Safronov66}