Skip to content

Commit 829200d

Browse files
committed
Merge branch 'fix/1293-production-zoom-scroll' into test-release/pr1295-workflow
2 parents d598a05 + 143ca19 commit 829200d

7 files changed

Lines changed: 411 additions & 105 deletions

File tree

frontend/src/components/Media/ImageViewer.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@ export const ImageViewer = forwardRef<ImageViewerRef, ImageViewerProps>(
1818
({ imagePath, alt, rotation, resetSignal }, ref) => {
1919
const zoomableImageRef = useRef<ZoomableImageRef>(null);
2020

21-
useImperativeHandle(ref, () => ({
22-
zoomIn: () => zoomableImageRef.current?.zoomIn(),
23-
zoomOut: () => zoomableImageRef.current?.zoomOut(),
24-
reset: () => zoomableImageRef.current?.reset(),
25-
}));
21+
useImperativeHandle(
22+
ref,
23+
() => ({
24+
zoomIn: () => zoomableImageRef.current?.zoomIn(),
25+
zoomOut: () => zoomableImageRef.current?.zoomOut(),
26+
reset: () => zoomableImageRef.current?.reset(),
27+
}),
28+
[],
29+
);
2630

2731
return (
2832
<ZoomableImage

frontend/src/components/Media/MediaThumbnails.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import React, { useRef, useEffect } from 'react';
22
import { convertFileSrc } from '@tauri-apps/api/core';
3+
import {
4+
PLACEHOLDER_IMAGE_SRC,
5+
handlePlaceholderImageError,
6+
} from '@/utils/imageFallback';
37

48
interface MediaThumbnailsProps {
59
images: Array<{
@@ -117,14 +121,10 @@ export const MediaThumbnails: React.FC<MediaThumbnailsProps> = ({
117121
} cursor-pointer transition-all duration-200 hover:scale-105`}
118122
>
119123
<img
120-
src={convertFileSrc(image.thumbnailPath) || '/placeholder.svg'}
124+
src={convertFileSrc(image.thumbnailPath) || PLACEHOLDER_IMAGE_SRC}
121125
alt={`thumbnail-${index}`}
122126
className="h-full w-full object-cover"
123-
onError={(e) => {
124-
const img = e.target as HTMLImageElement;
125-
img.onerror = null;
126-
img.src = '/placeholder.svg';
127-
}}
127+
onError={handlePlaceholderImageError}
128128
/>
129129
</div>
130130
))}

frontend/src/components/Media/ZoomableImage.tsx

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { useImperativeHandle, forwardRef } from 'react';
22
import { convertFileSrc } from '@tauri-apps/api/core';
33
import { useZoomTransform } from '@/hooks/useZoomTransform';
4+
import {
5+
PLACEHOLDER_IMAGE_SRC,
6+
handlePlaceholderImageError,
7+
} from '@/utils/imageFallback';
48

59
interface ZoomableImageProps {
610
imagePath: string;
@@ -35,11 +39,15 @@ export const ZoomableImage = forwardRef<ZoomableImageRef, ZoomableImageProps>(
3539
reset,
3640
} = useZoomTransform({ imagePath, rotation, resetSignal });
3741

38-
useImperativeHandle(ref, () => ({
39-
zoomIn,
40-
zoomOut,
41-
reset,
42-
}));
42+
useImperativeHandle(
43+
ref,
44+
() => ({
45+
zoomIn,
46+
zoomOut,
47+
reset,
48+
}),
49+
[zoomIn, zoomOut, reset],
50+
);
4351

4452
return (
4553
<div
@@ -75,26 +83,22 @@ export const ZoomableImage = forwardRef<ZoomableImageRef, ZoomableImageProps>(
7583
<img
7684
key={imagePath}
7785
ref={imageRef}
78-
src={convertFileSrc(imagePath) || '/placeholder.svg'}
86+
src={convertFileSrc(imagePath) || PLACEHOLDER_IMAGE_SRC}
7987
alt={alt}
8088
draggable={false}
81-
className="select-none"
8289
onLoad={handleImageLoad}
83-
onError={(e) => {
84-
const img = e.target as HTMLImageElement;
85-
img.onerror = null;
86-
img.src = '/placeholder.svg';
87-
}}
90+
onError={handlePlaceholderImageError}
8891
style={{
8992
position: contentDimensions ? 'absolute' : 'relative',
9093
left: `${imageOffset.left}px`,
9194
top: `${imageOffset.top}px`,
9295
width: rawDimensions ? `${rawDimensions.width}px` : undefined,
9396
height: rawDimensions ? `${rawDimensions.height}px` : undefined,
97+
// Override the framework's `img { max-width: 100% }` reset so the
98+
// image can scale beyond the viewport while zoomed.
9499
maxWidth: 'none',
95100
maxHeight: 'none',
96101
objectFit: 'contain',
97-
zIndex: 50,
98102
transform: `rotate(${rotation}deg)`,
99103
transformOrigin: 'center center',
100104
pointerEvents: 'none',

0 commit comments

Comments
 (0)