From 5f4a0f2881b9420f3a3f3fb6527352f58a99d9ea Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 28 Nov 2024 23:29:45 +0000 Subject: [PATCH] "Contain" images with missing dimensions instead of cropping them (#6828) * Show unknown aspect as "contain" for autosize * Fix a flash of wrong position when opening in lightbox * Fix last frame flash on Android --- .../ImageItem/ImageItem.android.tsx | 4 +- src/view/com/lightbox/ImageViewing/index.tsx | 37 +++++++++++++------ src/view/com/util/images/AutoSizedImage.tsx | 14 +++---- 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.android.tsx b/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.android.tsx index 8e046e5ba9..925158773c 100644 --- a/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.android.tsx +++ b/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.android.tsx @@ -392,9 +392,9 @@ const ImageItem = ({ img.thumbRect && (img.dimensions || img.thumbDimensions), + ) + ) +} + export default function ImageViewRoot({ lightbox: nextLightbox, onRequestClose, @@ -104,23 +113,19 @@ export default function ImageViewRoot({ return } - const canAnimate = - !PlatformInfo.getIsReducedMotionEnabled() && - nextLightbox.images.every( - img => img.thumbRect && (img.dimensions || img.thumbDimensions), - ) + const isAnimated = canAnimate(nextLightbox) // https://github.com/software-mansion/react-native-reanimated/issues/6677 rAF_FIXED(() => { openProgress.set(() => - canAnimate ? withClampedSpring(1, SLOW_SPRING) : 1, + isAnimated ? withClampedSpring(1, SLOW_SPRING) : 1, ) }) return () => { // https://github.com/software-mansion/react-native-reanimated/issues/6677 rAF_FIXED(() => { openProgress.set(() => - canAnimate ? withClampedSpring(0, SLOW_SPRING) : 0, + isAnimated ? withClampedSpring(0, SLOW_SPRING) : 0, ) }) } @@ -185,6 +190,7 @@ function ImageView({ openProgress: SharedValue }) { const {images, index: initialImageIndex} = lightbox + const isAnimated = useMemo(() => canAnimate(lightbox), [lightbox]) const [isScaled, setIsScaled] = useState(false) const [isDragging, setIsDragging] = useState(false) const [imageIndex, setImageIndex] = useState(initialImageIndex) @@ -194,10 +200,19 @@ function ImageView({ const isFlyingAway = useSharedValue(false) const containerStyle = useAnimatedStyle(() => { - if (openProgress.get() < 1 || isFlyingAway.get()) { - return {pointerEvents: 'none'} + if (openProgress.get() < 1) { + return { + pointerEvents: 'none', + opacity: isAnimated ? 1 : 0, + } + } + if (isFlyingAway.get()) { + return { + pointerEvents: 'none', + opacity: 1, + } } - return {pointerEvents: 'auto'} + return {pointerEvents: 'auto', opacity: 1} }) const backdropStyle = useAnimatedStyle(() => { diff --git a/src/view/com/util/images/AutoSizedImage.tsx b/src/view/com/util/images/AutoSizedImage.tsx index 617b9bec4b..a411b24bb8 100644 --- a/src/view/com/util/images/AutoSizedImage.tsx +++ b/src/view/com/util/images/AutoSizedImage.tsx @@ -85,10 +85,6 @@ export function AutoSizedImage({ if (Number.isNaN(aspectRatio)) { aspectRatio = undefined } - } else { - // If we don't know it synchronously, treat it like a square. - // We won't use fetched dimensions to avoid a layout shift. - aspectRatio = 1 } let constrained: number | undefined @@ -103,11 +99,13 @@ export function AutoSizedImage({ const cropDisabled = crop === 'none' const isCropped = rawIsCropped && !cropDisabled + const isContain = aspectRatio === undefined const hasAlt = !!image.alt const contents = ( { - fetchedDimsRef.current = { - width: e.source.width, - height: e.source.height, + if (!isContain) { + fetchedDimsRef.current = { + width: e.source.width, + height: e.source.height, + } } }} />