Factor props upwards
Also fix handling of missing aspectRatio
This commit is contained in:
@@ -20,7 +20,6 @@ import Animated, {
|
|||||||
} from 'react-native-reanimated'
|
} from 'react-native-reanimated'
|
||||||
import {Image, ImageStyle} from 'expo-image'
|
import {Image, ImageStyle} from 'expo-image'
|
||||||
|
|
||||||
import {useImageDimensions} from '#/lib/media/image-sizes'
|
|
||||||
import type {Dimensions as ImageDimensions, ImageSource} from '../../@types'
|
import type {Dimensions as ImageDimensions, ImageSource} from '../../@types'
|
||||||
import {
|
import {
|
||||||
applyRounding,
|
applyRounding,
|
||||||
@@ -55,6 +54,8 @@ type Props = {
|
|||||||
showControls: boolean
|
showControls: boolean
|
||||||
dismissSwipePan: PanGesture
|
dismissSwipePan: PanGesture
|
||||||
imageStyle: StyleProp<ImageStyle>
|
imageStyle: StyleProp<ImageStyle>
|
||||||
|
imageAspect: number | undefined
|
||||||
|
dimensions: ImageDimensions | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
const ImageItem = ({
|
const ImageItem = ({
|
||||||
@@ -64,12 +65,10 @@ const ImageItem = ({
|
|||||||
isPagingAndroid,
|
isPagingAndroid,
|
||||||
dismissSwipePan,
|
dismissSwipePan,
|
||||||
imageStyle,
|
imageStyle,
|
||||||
|
imageAspect,
|
||||||
|
dimensions,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const [isScaled, setIsScaled] = useState(false)
|
const [isScaled, setIsScaled] = useState(false)
|
||||||
const [imageAspect, imageDimensions] = useImageDimensions({
|
|
||||||
src: imageSrc.uri,
|
|
||||||
knownDimensions: imageSrc.dimensions,
|
|
||||||
})
|
|
||||||
const committedTransform = useSharedValue(initialTransform)
|
const committedTransform = useSharedValue(initialTransform)
|
||||||
const panTranslation = useSharedValue({x: 0, y: 0})
|
const panTranslation = useSharedValue({x: 0, y: 0})
|
||||||
const pinchOrigin = useSharedValue({x: 0, y: 0})
|
const pinchOrigin = useSharedValue({x: 0, y: 0})
|
||||||
@@ -155,14 +154,14 @@ const ImageItem = ({
|
|||||||
})
|
})
|
||||||
.onChange(e => {
|
.onChange(e => {
|
||||||
'worklet'
|
'worklet'
|
||||||
if (!imageDimensions) {
|
if (!dimensions) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Don't let the picture zoom in so close that it gets blurry.
|
// Don't let the picture zoom in so close that it gets blurry.
|
||||||
// Also, like in stock Android apps, don't let the user zoom out further than 1:1.
|
// Also, like in stock Android apps, don't let the user zoom out further than 1:1.
|
||||||
const [, , committedScale] = readTransform(committedTransform.value)
|
const [, , committedScale] = readTransform(committedTransform.value)
|
||||||
const maxCommittedScale =
|
const maxCommittedScale =
|
||||||
(imageDimensions.width / SCREEN.width) * MAX_ORIGINAL_IMAGE_ZOOM
|
(dimensions.width / SCREEN.width) * MAX_ORIGINAL_IMAGE_ZOOM
|
||||||
const minPinchScale = 1 / committedScale
|
const minPinchScale = 1 / committedScale
|
||||||
const maxPinchScale = maxCommittedScale / committedScale
|
const maxPinchScale = maxCommittedScale / committedScale
|
||||||
const nextPinchScale = Math.min(
|
const nextPinchScale = Math.min(
|
||||||
@@ -211,7 +210,7 @@ const ImageItem = ({
|
|||||||
.minPointers(isScaled ? 1 : 2)
|
.minPointers(isScaled ? 1 : 2)
|
||||||
.onChange(e => {
|
.onChange(e => {
|
||||||
'worklet'
|
'worklet'
|
||||||
if (!imageDimensions) {
|
if (!dimensions) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const nextPanTranslation = {x: e.translationX, y: e.translationY}
|
const nextPanTranslation = {x: e.translationX, y: e.translationY}
|
||||||
@@ -259,7 +258,7 @@ const ImageItem = ({
|
|||||||
.numberOfTaps(2)
|
.numberOfTaps(2)
|
||||||
.onEnd(e => {
|
.onEnd(e => {
|
||||||
'worklet'
|
'worklet'
|
||||||
if (!imageDimensions || !imageAspect) {
|
if (!dimensions || !imageAspect) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const [, , committedScale] = readTransform(committedTransform.value)
|
const [, , committedScale] = readTransform(committedTransform.value)
|
||||||
@@ -279,7 +278,7 @@ const ImageItem = ({
|
|||||||
)
|
)
|
||||||
// But don't zoom in so close that the picture gets blurry.
|
// But don't zoom in so close that the picture gets blurry.
|
||||||
const maxScale =
|
const maxScale =
|
||||||
(imageDimensions.width / SCREEN.width) * MAX_ORIGINAL_IMAGE_ZOOM
|
(dimensions.width / SCREEN.width) * MAX_ORIGINAL_IMAGE_ZOOM
|
||||||
const scale = Math.min(candidateScale, maxScale)
|
const scale = Math.min(candidateScale, maxScale)
|
||||||
|
|
||||||
// Calculate where we would be if the user pinched into the double tapped point.
|
// Calculate where we would be if the user pinched into the double tapped point.
|
||||||
@@ -321,19 +320,7 @@ const ImageItem = ({
|
|||||||
source={{uri: imageSrc.uri}}
|
source={{uri: imageSrc.uri}}
|
||||||
placeholderContentFit="cover"
|
placeholderContentFit="cover"
|
||||||
placeholder={{uri: imageSrc.thumbUri}}
|
placeholder={{uri: imageSrc.thumbUri}}
|
||||||
style={[
|
style={imageStyle}
|
||||||
{
|
|
||||||
width: SCREEN.width,
|
|
||||||
height: imageAspect ? SCREEN.width / imageAspect : undefined,
|
|
||||||
borderRadius:
|
|
||||||
imageSrc.type === 'circle-avi'
|
|
||||||
? SCREEN.width / 2
|
|
||||||
: imageSrc.type === 'rect-avi'
|
|
||||||
? 20
|
|
||||||
: 0,
|
|
||||||
},
|
|
||||||
imageStyle,
|
|
||||||
]}
|
|
||||||
accessibilityLabel={imageSrc.alt}
|
accessibilityLabel={imageSrc.alt}
|
||||||
accessibilityHint=""
|
accessibilityHint=""
|
||||||
accessibilityIgnoresInvertColors
|
accessibilityIgnoresInvertColors
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ import Animated, {runOnJS, useAnimatedRef} from 'react-native-reanimated'
|
|||||||
import {Image, ImageStyle} from 'expo-image'
|
import {Image, ImageStyle} from 'expo-image'
|
||||||
|
|
||||||
import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED'
|
import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED'
|
||||||
import {useImageDimensions} from '#/lib/media/image-sizes'
|
import {Dimensions as ImageDimensions, ImageSource} from '../../@types'
|
||||||
import {ImageSource} from '../../@types'
|
|
||||||
|
|
||||||
const AnimatedImage = Animated.createAnimatedComponent(Image)
|
const AnimatedImage = Animated.createAnimatedComponent(Image)
|
||||||
|
|
||||||
@@ -40,25 +39,24 @@ type Props = {
|
|||||||
showControls: boolean
|
showControls: boolean
|
||||||
dismissSwipePan: PanGesture | null
|
dismissSwipePan: PanGesture | null
|
||||||
imageStyle: StyleProp<ImageStyle>
|
imageStyle: StyleProp<ImageStyle>
|
||||||
|
imageAspect: number | undefined
|
||||||
|
dimensions: ImageDimensions | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
const ImageItem = ({
|
const ImageItem = ({
|
||||||
imageSrc,
|
imageSrc,
|
||||||
|
dimensions,
|
||||||
onTap,
|
onTap,
|
||||||
onZoom,
|
onZoom,
|
||||||
showControls,
|
showControls,
|
||||||
dismissSwipePan,
|
dismissSwipePan,
|
||||||
imageStyle,
|
imageStyle,
|
||||||
|
imageAspect,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const scrollViewRef = useAnimatedRef<Animated.ScrollView>()
|
const scrollViewRef = useAnimatedRef<Animated.ScrollView>()
|
||||||
|
|
||||||
const [scaled, setScaled] = useState(false)
|
const [scaled, setScaled] = useState(false)
|
||||||
const [imageAspect, imageDimensions] = useImageDimensions({
|
const maxZoomScale = dimensions
|
||||||
src: imageSrc.uri,
|
? (dimensions.width / SCREEN.width) * MAX_ORIGINAL_IMAGE_ZOOM
|
||||||
knownDimensions: imageSrc.dimensions,
|
|
||||||
})
|
|
||||||
const maxZoomScale = imageDimensions
|
|
||||||
? (imageDimensions.width / SCREEN.width) * MAX_ORIGINAL_IMAGE_ZOOM
|
|
||||||
: 1
|
: 1
|
||||||
|
|
||||||
const scrollHandler = useAnimatedScrollHandler({
|
const scrollHandler = useAnimatedScrollHandler({
|
||||||
@@ -158,19 +156,7 @@ const ImageItem = ({
|
|||||||
source={{uri: imageSrc.uri}}
|
source={{uri: imageSrc.uri}}
|
||||||
placeholderContentFit="cover"
|
placeholderContentFit="cover"
|
||||||
placeholder={{uri: imageSrc.thumbUri}}
|
placeholder={{uri: imageSrc.thumbUri}}
|
||||||
style={[
|
style={imageStyle}
|
||||||
{
|
|
||||||
width: SCREEN.width,
|
|
||||||
height: imageAspect ? SCREEN.width / imageAspect : undefined,
|
|
||||||
borderRadius:
|
|
||||||
imageSrc.type === 'circle-avi'
|
|
||||||
? SCREEN.width / 2
|
|
||||||
: imageSrc.type === 'rect-avi'
|
|
||||||
? 20
|
|
||||||
: 0,
|
|
||||||
},
|
|
||||||
imageStyle,
|
|
||||||
]}
|
|
||||||
accessibilityLabel={imageSrc.alt}
|
accessibilityLabel={imageSrc.alt}
|
||||||
accessibilityHint=""
|
accessibilityHint=""
|
||||||
enableLiveTextInteraction={showControls && !scaled}
|
enableLiveTextInteraction={showControls && !scaled}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {StyleProp, View} from 'react-native'
|
|||||||
import {PanGesture} from 'react-native-gesture-handler'
|
import {PanGesture} from 'react-native-gesture-handler'
|
||||||
import {ImageStyle} from 'expo-image'
|
import {ImageStyle} from 'expo-image'
|
||||||
|
|
||||||
import {ImageSource} from '../../@types'
|
import {Dimensions as ImageDimensions, ImageSource} from '../../@types'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
imageSrc: ImageSource
|
imageSrc: ImageSource
|
||||||
@@ -16,6 +16,8 @@ type Props = {
|
|||||||
showControls: boolean
|
showControls: boolean
|
||||||
dismissSwipePan: PanGesture | null
|
dismissSwipePan: PanGesture | null
|
||||||
imageStyle: StyleProp<ImageStyle>
|
imageStyle: StyleProp<ImageStyle>
|
||||||
|
imageAspect: number | undefined
|
||||||
|
dimensions: ImageDimensions | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
const ImageItem = (_props: Props) => {
|
const ImageItem = (_props: Props) => {
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import {Edge, SafeAreaView} from 'react-native-safe-area-context'
|
|||||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||||
import {Trans} from '@lingui/macro'
|
import {Trans} from '@lingui/macro'
|
||||||
|
|
||||||
|
import {useImageDimensions} from '#/lib/media/image-sizes'
|
||||||
import {colors, s} from '#/lib/styles'
|
import {colors, s} from '#/lib/styles'
|
||||||
import {isAndroid, isIOS} from '#/platform/detection'
|
import {isAndroid, isIOS} from '#/platform/detection'
|
||||||
import {Lightbox} from '#/state/lightbox'
|
import {Lightbox} from '#/state/lightbox'
|
||||||
@@ -262,20 +263,22 @@ function LightboxPage({
|
|||||||
dismissSwipeTranslateY: SharedValue<number>
|
dismissSwipeTranslateY: SharedValue<number>
|
||||||
dismissSwipePan: PanGesture
|
dismissSwipePan: PanGesture
|
||||||
}) {
|
}) {
|
||||||
const {thumbRect, dimensions} = imageSrc
|
const {thumbRect, dimensions: knownDimensions, type} = imageSrc
|
||||||
const imageAspect = dimensions
|
const [imageAspect, dimensions] = useImageDimensions({
|
||||||
? dimensions.width / dimensions.height
|
src: imageSrc.uri,
|
||||||
: undefined
|
knownDimensions,
|
||||||
|
})
|
||||||
|
|
||||||
const finalWidth = SCREEN.width
|
const finalWidth = SCREEN.width
|
||||||
const finalHeight = imageAspect ? SCREEN.width / imageAspect : undefined
|
const finalHeight = imageAspect ? SCREEN.width / imageAspect : undefined
|
||||||
|
|
||||||
const interpolation = useDerivedValue(() => {
|
const interpolation = useDerivedValue(() => {
|
||||||
if (isActive && thumbRect && dimensions && openProgress.value < 1) {
|
if (isActive && thumbRect && knownDimensions && openProgress.value < 1) {
|
||||||
return interpolateTransform(
|
return interpolateTransform(
|
||||||
openProgress.value,
|
openProgress.value,
|
||||||
thumbRect,
|
thumbRect,
|
||||||
SCREEN,
|
SCREEN,
|
||||||
dimensions,
|
knownDimensions,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
const translateY = isActive ? dismissSwipeTranslateY.value : 0
|
const translateY = isActive ? dismissSwipeTranslateY.value : 0
|
||||||
@@ -299,6 +302,8 @@ function LightboxPage({
|
|||||||
return {
|
return {
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
|
borderRadius:
|
||||||
|
type === 'circle-avi' ? SCREEN.width / 2 : type === 'rect-avi' ? 20 : 0,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -313,6 +318,8 @@ function LightboxPage({
|
|||||||
showControls={showControls}
|
showControls={showControls}
|
||||||
dismissSwipePan={isActive ? dismissSwipePan : null}
|
dismissSwipePan={isActive ? dismissSwipePan : null}
|
||||||
imageStyle={imageStyle}
|
imageStyle={imageStyle}
|
||||||
|
imageAspect={imageAspect}
|
||||||
|
dimensions={dimensions}
|
||||||
/>
|
/>
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user