Measure tapped image coordinates before opening lightbox (#6001)
* Measure image on press * Pass dimensions to the lightbox component
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import React from 'react'
|
||||
import {Pressable, StyleProp, View, ViewStyle} from 'react-native'
|
||||
import Animated, {AnimatedRef, useAnimatedRef} from 'react-native-reanimated'
|
||||
import {Image, ImageStyle} from 'expo-image'
|
||||
import {AppBskyEmbedImages} from '@atproto/api'
|
||||
import {msg} from '@lingui/macro'
|
||||
@@ -16,7 +17,10 @@ type EventFunction = (index: number) => void
|
||||
interface Props {
|
||||
images: AppBskyEmbedImages.ViewImage[]
|
||||
index: number
|
||||
onPress?: EventFunction
|
||||
onPress?: (
|
||||
index: number,
|
||||
containerRef: AnimatedRef<React.Component<{}, {}, any>>,
|
||||
) => void
|
||||
onLongPress?: EventFunction
|
||||
onPressIn?: EventFunction
|
||||
imageStyle?: StyleProp<ImageStyle>
|
||||
@@ -41,10 +45,11 @@ export function GalleryItem({
|
||||
const hasAlt = !!image.alt
|
||||
const hideBadges =
|
||||
viewContext === PostEmbedViewContext.FeedEmbedRecordWithMedia
|
||||
const containerRef = useAnimatedRef()
|
||||
return (
|
||||
<View style={a.flex_1}>
|
||||
<Animated.View style={a.flex_1} ref={containerRef}>
|
||||
<Pressable
|
||||
onPress={onPress ? () => onPress(index) : undefined}
|
||||
onPress={onPress ? () => onPress(index, containerRef) : undefined}
|
||||
onPressIn={onPressIn ? () => onPressIn(index) : undefined}
|
||||
onLongPress={onLongPress ? () => onLongPress(index) : undefined}
|
||||
style={[
|
||||
@@ -95,6 +100,6 @@ export function GalleryItem({
|
||||
</Text>
|
||||
</View>
|
||||
) : null}
|
||||
</View>
|
||||
</Animated.View>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from 'react'
|
||||
import {StyleProp, StyleSheet, View, ViewStyle} from 'react-native'
|
||||
import {AnimatedRef} from 'react-native-reanimated'
|
||||
import {AppBskyEmbedImages} from '@atproto/api'
|
||||
|
||||
import {PostEmbedViewContext} from '#/view/com/util/post-embeds/types'
|
||||
@@ -8,7 +9,10 @@ import {GalleryItem} from './Gallery'
|
||||
|
||||
interface ImageLayoutGridProps {
|
||||
images: AppBskyEmbedImages.ViewImage[]
|
||||
onPress?: (index: number) => void
|
||||
onPress?: (
|
||||
index: number,
|
||||
containerRef: AnimatedRef<React.Component<{}, {}, any>>,
|
||||
) => void
|
||||
onLongPress?: (index: number) => void
|
||||
onPressIn?: (index: number) => void
|
||||
style?: StyleProp<ViewStyle>
|
||||
@@ -36,7 +40,10 @@ export function ImageLayoutGrid({style, ...props}: ImageLayoutGridProps) {
|
||||
|
||||
interface ImageLayoutGridInnerProps {
|
||||
images: AppBskyEmbedImages.ViewImage[]
|
||||
onPress?: (index: number) => void
|
||||
onPress?: (
|
||||
index: number,
|
||||
containerRef: AnimatedRef<React.Component<{}, {}, any>>,
|
||||
) => void
|
||||
onLongPress?: (index: number) => void
|
||||
onPressIn?: (index: number) => void
|
||||
viewContext?: PostEmbedViewContext
|
||||
|
||||
@@ -6,6 +6,14 @@ import {
|
||||
View,
|
||||
ViewStyle,
|
||||
} from 'react-native'
|
||||
import Animated, {
|
||||
AnimatedRef,
|
||||
measure,
|
||||
MeasuredDimensions,
|
||||
runOnJS,
|
||||
runOnUI,
|
||||
useAnimatedRef,
|
||||
} from 'react-native-reanimated'
|
||||
import {Image} from 'expo-image'
|
||||
import {
|
||||
AppBskyEmbedExternal,
|
||||
@@ -61,6 +69,7 @@ export function PostEmbeds({
|
||||
viewContext?: PostEmbedViewContext
|
||||
}) {
|
||||
const {openLightbox} = useLightboxControls()
|
||||
const containerRef = useAnimatedRef()
|
||||
|
||||
// quote post with media
|
||||
// =
|
||||
@@ -138,13 +147,27 @@ export function PostEmbeds({
|
||||
alt: img.alt,
|
||||
aspectRatio: img.aspectRatio,
|
||||
}))
|
||||
const _openLightbox = (index: number) => {
|
||||
const _openLightbox = (
|
||||
index: number,
|
||||
thumbDims: MeasuredDimensions | null,
|
||||
) => {
|
||||
openLightbox({
|
||||
type: 'images',
|
||||
images: items,
|
||||
index,
|
||||
thumbDims,
|
||||
})
|
||||
}
|
||||
const onPress = (
|
||||
index: number,
|
||||
ref: AnimatedRef<React.Component<{}, {}, any>>,
|
||||
) => {
|
||||
runOnUI(() => {
|
||||
'worklet'
|
||||
const dims = measure(ref)
|
||||
runOnJS(_openLightbox)(index, dims)
|
||||
})()
|
||||
}
|
||||
const onPressIn = (_: number) => {
|
||||
InteractionManager.runAfterInteractions(() => {
|
||||
Image.prefetch(items.map(i => i.uri))
|
||||
@@ -155,7 +178,7 @@ export function PostEmbeds({
|
||||
const image = images[0]
|
||||
return (
|
||||
<ContentHider modui={moderation?.ui('contentMedia')}>
|
||||
<View style={[a.mt_sm, style]}>
|
||||
<Animated.View ref={containerRef} style={[a.mt_sm, style]}>
|
||||
<AutoSizedImage
|
||||
crop={
|
||||
viewContext === PostEmbedViewContext.ThreadHighlighted
|
||||
@@ -166,13 +189,13 @@ export function PostEmbeds({
|
||||
: 'constrained'
|
||||
}
|
||||
image={image}
|
||||
onPress={() => _openLightbox(0)}
|
||||
onPress={() => onPress(0, containerRef)}
|
||||
onPressIn={() => onPressIn(0)}
|
||||
hideBadge={
|
||||
viewContext === PostEmbedViewContext.FeedEmbedRecordWithMedia
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</Animated.View>
|
||||
</ContentHider>
|
||||
)
|
||||
}
|
||||
@@ -182,7 +205,7 @@ export function PostEmbeds({
|
||||
<View style={[a.mt_sm, style]}>
|
||||
<ImageLayoutGrid
|
||||
images={embed.images}
|
||||
onPress={_openLightbox}
|
||||
onPress={onPress}
|
||||
onPressIn={onPressIn}
|
||||
viewContext={viewContext}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user