your personal website on atproto - mirror blento.app

Compare changes

Choose any two refs to compare.

+29 -6
+1 -1
.gitignore
··· 22 22 vite.config.js.timestamp-* 23 23 vite.config.ts.timestamp-* 24 24 25 - react-grid-layout 25 + references
+28 -5
src/lib/components/qr/qrOverlay.svelte.ts
··· 18 18 const LONG_PRESS_DURATION = 500; 19 19 let longPressTimer: ReturnType<typeof setTimeout> | null = null; 20 20 let isLongPress = false; 21 + let touchActive = false; 22 + 23 + // Prevent iOS link preview on long-press 24 + const originalCallout = node.style.getPropertyValue('-webkit-touch-callout'); 25 + node.style.setProperty('-webkit-touch-callout', 'none'); 21 26 22 27 function getHref() { 23 28 return params.href || (node as HTMLAnchorElement).href || ''; 24 29 } 25 30 26 - function startLongPress() { 31 + function startLongPress(e: PointerEvent) { 27 32 if (params.disabled) return; 33 + // Only start long press for primary button (touch/left-click), not right-click 34 + if (e.button !== 0) return; 35 + touchActive = e.pointerType === 'touch'; 28 36 isLongPress = false; 29 37 longPressTimer = setTimeout(() => { 30 38 isLongPress = true; ··· 37 45 clearTimeout(longPressTimer); 38 46 longPressTimer = null; 39 47 } 48 + touchActive = false; 40 49 } 41 50 42 51 function handleClick(e: MouseEvent) { 43 52 if (isLongPress) { 44 53 e.preventDefault(); 45 54 isLongPress = false; 55 + return; 56 + } 57 + 58 + // Shift-click opens QR modal 59 + if (e.shiftKey && !params.disabled) { 60 + e.preventDefault(); 61 + openModal?.(getHref(), params.context ?? {}); 46 62 } 47 63 } 48 64 49 - function handleContextMenu(e: MouseEvent) { 50 - if (params.disabled) return; 51 - e.preventDefault(); 52 - openModal?.(getHref(), params.context ?? {}); 65 + function handleContextMenu(e: Event) { 66 + // Prevent context menu during touch to avoid iOS preview 67 + if (touchActive || isLongPress) { 68 + e.preventDefault(); 69 + } 53 70 } 54 71 55 72 node.addEventListener('pointerdown', startLongPress); ··· 71 88 node.removeEventListener('click', handleClick); 72 89 node.removeEventListener('contextmenu', handleContextMenu); 73 90 cancelLongPress(); 91 + // Restore original style 92 + if (originalCallout) { 93 + node.style.setProperty('-webkit-touch-callout', originalCallout); 94 + } else { 95 + node.style.removeProperty('-webkit-touch-callout'); 96 + } 74 97 } 75 98 }; 76 99 }