Skip to content

Commit

Permalink
Measure tapped image coordinates before opening lightbox (#6001)
Browse files Browse the repository at this point in the history
* Measure image on press

* Pass dimensions to the lightbox component
  • Loading branch information
gaearon authored Oct 31, 2024
1 parent 6f4703e commit 1e32327
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 11 deletions.
1 change: 1 addition & 0 deletions src/screens/Profile/Header/Shell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ let ProfileHeaderShell = ({
openLightbox({
type: 'profile-image',
profile: profile,
thumbDims: null,
})
}
}, [openLightbox, profile, moderation])
Expand Down
3 changes: 3 additions & 0 deletions src/state/lightbox.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import React from 'react'
import type {MeasuredDimensions} from 'react-native-reanimated'
import {AppBskyActorDefs} from '@atproto/api'

import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'

type ProfileImageLightbox = {
type: 'profile-image'
profile: AppBskyActorDefs.ProfileViewDetailed
thumbDims: null
}

type ImagesLightboxItem = {
Expand All @@ -17,6 +19,7 @@ type ImagesLightboxItem = {
type ImagesLightbox = {
type: 'images'
images: ImagesLightboxItem[]
thumbDims: MeasuredDimensions | null
index: number
}

Expand Down
3 changes: 3 additions & 0 deletions src/view/com/lightbox/ImageViewing/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import React, {ComponentType, useCallback, useMemo, useState} from 'react'
import {Platform, StyleSheet, View} from 'react-native'
import PagerView from 'react-native-pager-view'
import {MeasuredDimensions} from 'react-native-reanimated'
import Animated, {useAnimatedStyle, withSpring} from 'react-native-reanimated'
import {Edge, SafeAreaView} from 'react-native-safe-area-context'

Expand All @@ -20,6 +21,7 @@ import ImageItem from './components/ImageItem/ImageItem'

type Props = {
images: ImageSource[]
thumbDims: MeasuredDimensions | null
initialImageIndex: number
visible: boolean
onRequestClose: () => void
Expand All @@ -32,6 +34,7 @@ const DEFAULT_BG_COLOR = '#000'

function ImageViewing({
images,
thumbDims: _thumbDims, // TODO: Pass down and use for animation.
initialImageIndex,
visible,
onRequestClose,
Expand Down
2 changes: 2 additions & 0 deletions src/view/com/lightbox/Lightbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export function Lightbox() {
{uri: opts.profile.avatar || '', thumbUri: opts.profile.avatar || ''},
]}
initialImageIndex={0}
thumbDims={opts.thumbDims}
visible
onRequestClose={onClose}
FooterComponent={LightboxFooter}
Expand All @@ -46,6 +47,7 @@ export function Lightbox() {
<ImageView
images={opts.images.map(img => ({...img}))}
initialImageIndex={opts.index}
thumbDims={opts.thumbDims}
visible
onRequestClose={onClose}
FooterComponent={LightboxFooter}
Expand Down
1 change: 1 addition & 0 deletions src/view/com/profile/ProfileSubpageHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export function ProfileSubpageHeader({
type: 'images',
images: [{uri: avatar, thumbUri: avatar}],
index: 0,
thumbDims: null,
})
}
}, [openLightbox, avatar])
Expand Down
13 changes: 9 additions & 4 deletions src/view/com/util/images/Gallery.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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>
Expand All @@ -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={[
Expand Down Expand Up @@ -95,6 +100,6 @@ export function GalleryItem({
</Text>
</View>
) : null}
</View>
</Animated.View>
)
}
11 changes: 9 additions & 2 deletions src/view/com/util/images/ImageLayoutGrid.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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>
Expand Down Expand Up @@ -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
Expand Down
33 changes: 28 additions & 5 deletions src/view/com/util/post-embeds/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -61,6 +69,7 @@ export function PostEmbeds({
viewContext?: PostEmbedViewContext
}) {
const {openLightbox} = useLightboxControls()
const containerRef = useAnimatedRef()

// quote post with media
// =
Expand Down Expand Up @@ -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))
Expand All @@ -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
Expand All @@ -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>
)
}
Expand All @@ -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}
/>
Expand Down

0 comments on commit 1e32327

Please sign in to comment.