your personal website on atproto - mirror
blento.app
1import type { QRContext } from './QRCodeModal.svelte';
2
3// Global state for QR modal
4let openModal: ((href: string, context: QRContext) => void) | null = null;
5
6export function registerQRModal(fn: (href: string, context: QRContext) => void) {
7 openModal = fn;
8}
9
10export function unregisterQRModal() {
11 openModal = null;
12}
13
14export function qrOverlay(
15 node: HTMLElement,
16 params: { href?: string; context?: QRContext; disabled?: boolean } = {}
17) {
18 const LONG_PRESS_DURATION = 500;
19 let longPressTimer: ReturnType<typeof setTimeout> | null = null;
20 let isLongPress = false;
21
22 function getHref() {
23 return params.href || (node as HTMLAnchorElement).href || '';
24 }
25
26 function startLongPress() {
27 if (params.disabled) return;
28 isLongPress = false;
29 longPressTimer = setTimeout(() => {
30 isLongPress = true;
31 openModal?.(getHref(), params.context ?? {});
32 }, LONG_PRESS_DURATION);
33 }
34
35 function cancelLongPress() {
36 if (longPressTimer) {
37 clearTimeout(longPressTimer);
38 longPressTimer = null;
39 }
40 }
41
42 function handleClick(e: MouseEvent) {
43 if (isLongPress) {
44 e.preventDefault();
45 isLongPress = false;
46 }
47 }
48
49 function handleContextMenu(e: MouseEvent) {
50 if (params.disabled) return;
51 e.preventDefault();
52 openModal?.(getHref(), params.context ?? {});
53 }
54
55 node.addEventListener('pointerdown', startLongPress);
56 node.addEventListener('pointerup', cancelLongPress);
57 node.addEventListener('pointercancel', cancelLongPress);
58 node.addEventListener('pointerleave', cancelLongPress);
59 node.addEventListener('click', handleClick);
60 node.addEventListener('contextmenu', handleContextMenu);
61
62 return {
63 update(newParams: { href?: string; context?: QRContext; disabled?: boolean }) {
64 params = newParams;
65 },
66 destroy() {
67 node.removeEventListener('pointerdown', startLongPress);
68 node.removeEventListener('pointerup', cancelLongPress);
69 node.removeEventListener('pointercancel', cancelLongPress);
70 node.removeEventListener('pointerleave', cancelLongPress);
71 node.removeEventListener('click', handleClick);
72 node.removeEventListener('contextmenu', handleContextMenu);
73 cancelLongPress();
74 }
75 };
76}