swipe bug fix
This commit is contained in:
@@ -4,15 +4,16 @@ import { createPortal } from 'react-dom';
|
|||||||
export default function ImageLightbox({ src, onClose }) {
|
export default function ImageLightbox({ src, onClose }) {
|
||||||
const overlayRef = useRef(null);
|
const overlayRef = useRef(null);
|
||||||
|
|
||||||
// Close on Escape
|
// Close on Escape; signal global pinch handler to stand down while open
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handler = (e) => { if (e.key === 'Escape') onClose(); };
|
const handler = (e) => { if (e.key === 'Escape') onClose(); };
|
||||||
window.addEventListener('keydown', handler);
|
window.addEventListener('keydown', handler);
|
||||||
// Prevent body scroll while open
|
|
||||||
document.body.style.overflow = 'hidden';
|
document.body.style.overflow = 'hidden';
|
||||||
|
document.documentElement.dataset.lightboxOpen = '1';
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('keydown', handler);
|
window.removeEventListener('keydown', handler);
|
||||||
document.body.style.overflow = '';
|
document.body.style.overflow = '';
|
||||||
|
delete document.documentElement.dataset.lightboxOpen;
|
||||||
};
|
};
|
||||||
}, [onClose]);
|
}, [onClose]);
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,9 @@ if ('serviceWorker' in navigator) {
|
|||||||
|
|
||||||
document.addEventListener('touchmove', function (e) {
|
document.addEventListener('touchmove', function (e) {
|
||||||
if (e.touches.length === 2 && pinchStartDist !== null) {
|
if (e.touches.length === 2 && pinchStartDist !== null) {
|
||||||
// Two-finger pinch: scale fonts, not viewport
|
// Two-finger pinch: scale fonts, not viewport.
|
||||||
|
// Skip when a lightbox is open — let the browser handle pinch natively there.
|
||||||
|
if (document.documentElement.dataset.lightboxOpen) return;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const ratio = getTouchDist(e) / pinchStartDist;
|
const ratio = getTouchDist(e) / pinchStartDist;
|
||||||
const newScale = Math.min(MAX_SCALE, Math.max(MIN_SCALE, pinchStartScale * ratio));
|
const newScale = Math.min(MAX_SCALE, Math.max(MIN_SCALE, pinchStartScale * ratio));
|
||||||
|
|||||||
@@ -455,11 +455,15 @@ export default function Chat() {
|
|||||||
setUnreadGroups(prev => { const next = new Map(prev); next.delete(id); return next; });
|
setUnreadGroups(prev => { const next = new Map(prev); next.delete(id); return next; });
|
||||||
};
|
};
|
||||||
|
|
||||||
// Establish one history sentinel on mount (mobile only) so back gestures are
|
// Establish two history entries on mount (mobile only):
|
||||||
// always interceptable without accumulating extra entries.
|
// floor — marks the true exit point; always stays below the sentinel
|
||||||
|
// sentinel — intercepted by handlePopState on every back gesture
|
||||||
|
// Two entries are required so that iOS fires popstate (same-document navigation)
|
||||||
|
// before exiting, giving the handler a chance to push a new sentinel.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (window.innerWidth < 768) {
|
if (window.innerWidth < 768) {
|
||||||
window.history.replaceState({ rc: 'chat' }, '');
|
window.history.replaceState({ rc: 'floor' }, '');
|
||||||
|
window.history.pushState({ rc: 'chat' }, '');
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -486,8 +490,11 @@ export default function Chat() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Already at root (Messages list, no chat open) — let the browser handle
|
// Already at root (Messages list, no chat open) — we just popped the sentinel
|
||||||
// it so the next gesture actually exits the PWA. Don't re-push.
|
// and are now on the floor entry. Step one more back so the browser exits the
|
||||||
|
// PWA (or navigates to the previous URL). Without this explicit go(-1), iOS
|
||||||
|
// leaves the user stranded on the invisible floor state.
|
||||||
|
window.history.go(-1);
|
||||||
};
|
};
|
||||||
window.addEventListener('popstate', handlePopState);
|
window.addEventListener('popstate', handlePopState);
|
||||||
return () => window.removeEventListener('popstate', handlePopState);
|
return () => window.removeEventListener('popstate', handlePopState);
|
||||||
|
|||||||
Reference in New Issue
Block a user