This commit is contained in:
2025-11-02 12:12:11 +01:00
parent e7e7881772
commit 1135873968
2 changed files with 54 additions and 21 deletions
+53 -20
View File
@@ -17,6 +17,8 @@ const ensureDocumentRoot = () => {
return document.body;
};
const CLICK_DELAY_MS = 240;
const PreviewZoomOverlay = ({
open = false,
display = null,
@@ -34,6 +36,7 @@ const PreviewZoomOverlay = ({
const previouslyFocusedRef = useRef(null);
const visibilityTimerRef = useRef(null);
const displayTimerRef = useRef(null);
const clickTimerRef = useRef(null);
useEffect(() => {
if (display?.url) {
@@ -86,12 +89,20 @@ const PreviewZoomOverlay = ({
if (displayTimerRef.current) {
cancelAnimationFrame(displayTimerRef.current);
}
if (clickTimerRef.current) {
clearTimeout(clickTimerRef.current);
clickTimerRef.current = null;
}
}, []);
useEffect(() => {
setIsNativeScale(false);
setNaturalSize({ width: null, height: null });
focusRef.current = null;
if (clickTimerRef.current) {
clearTimeout(clickTimerRef.current);
clickTimerRef.current = null;
}
const scrollEl = scrollRef.current;
if (scrollEl) {
scrollEl.scrollLeft = 0;
@@ -198,6 +209,45 @@ const PreviewZoomOverlay = ({
const effectiveDisplay = activeDisplay;
const navVisible = Boolean(effectiveDisplay?.canGoPrev || effectiveDisplay?.canGoNext);
const toggleZoomAtPoint = (clientX, clientY) => {
const img = imageRef.current;
setIsNativeScale((current) => {
if (!current && img) {
const rect = img.getBoundingClientRect();
const xRatio = rect.width > 0 ? (clientX - rect.left) / rect.width : 0.5;
const yRatio = rect.height > 0 ? (clientY - rect.top) / rect.height : 0.5;
focusRef.current = {
xRatio: clamp(xRatio, 0, 1),
yRatio: clamp(yRatio, 0, 1),
};
} else {
focusRef.current = null;
}
return !current;
});
};
const handleImagePointerDown = (event) => {
event.stopPropagation();
if (event.button && event.button !== 0) {
return;
}
if (event.pointerType === 'touch' && event.isPrimary === false) {
return;
}
if (clickTimerRef.current) {
clearTimeout(clickTimerRef.current);
clickTimerRef.current = null;
toggleZoomAtPoint(event.clientX, event.clientY);
return;
}
clickTimerRef.current = setTimeout(() => {
clickTimerRef.current = null;
onClose();
}, CLICK_DELAY_MS);
};
const stageClassName = [
'preview-zoom__stage',
]
@@ -225,11 +275,13 @@ const PreviewZoomOverlay = ({
height: naturalSize.height ? `${naturalSize.height}px` : 'auto',
maxWidth: 'none',
maxHeight: 'none',
touchAction: 'manipulation',
}
: {
cursor: 'zoom-in',
maxWidth: '95vw',
maxHeight: '95vh',
touchAction: 'manipulation',
};
return createPortal(
@@ -263,26 +315,7 @@ const PreviewZoomOverlay = ({
height: event.currentTarget.naturalHeight || null,
});
}}
onClick={(event) => {
event.stopPropagation();
if (!isNativeScale) {
const img = imageRef.current;
if (img) {
const rect = img.getBoundingClientRect();
const xRatio = rect.width > 0 ? (event.clientX - rect.left) / rect.width : 0.5;
const yRatio = rect.height > 0 ? (event.clientY - rect.top) / rect.height : 0.5;
focusRef.current = {
xRatio: clamp(xRatio, 0, 1),
yRatio: clamp(yRatio, 0, 1),
};
} else {
focusRef.current = null;
}
} else {
focusRef.current = null;
}
setIsNativeScale((current) => !current);
}}
onPointerDown={handleImagePointerDown}
style={imageStyle}
/>
</div>
+1 -1
View File
@@ -2482,7 +2482,7 @@ button.danger:hover:not([disabled]) {
position: absolute;
top: 0;
right: 0;
width: var(--detail-panel-width);
width: min(100vw, var(--detail-panel-width));
min-height: 100vh;
height: 100%;
height: 100%;