[new arch] experiment - use animatedview/animatedref to measure rect for lightbox (#8298)
* more upgrades * use animatedview/animatedref for measurements in lightbox * rm usehandleref * downgrade dynamic app icon * more bumps that let the thing build on ios * bumps that let it build for ios * bump expo --------- Co-authored-by: Samuel Newman <mozzius@protonmail.com>
This commit is contained in:
+1
-1
@@ -130,7 +130,7 @@
|
|||||||
"emoji-mart": "^5.5.2",
|
"emoji-mart": "^5.5.2",
|
||||||
"emoji-regex": "^10.4.0",
|
"emoji-regex": "^10.4.0",
|
||||||
"eventemitter3": "^5.0.1",
|
"eventemitter3": "^5.0.1",
|
||||||
"expo": "53.0.1",
|
"expo": "53.0.2",
|
||||||
"expo-application": "~6.1.3",
|
"expo-application": "~6.1.3",
|
||||||
"expo-blur": "^14.1.3",
|
"expo-blur": "^14.1.3",
|
||||||
"expo-build-properties": "~0.14.5",
|
"expo-build-properties": "~0.14.5",
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
import {useState} from 'react'
|
|
||||||
import {AnimatedRef, measure, MeasuredDimensions} from 'react-native-reanimated'
|
|
||||||
|
|
||||||
export type HandleRef = {
|
|
||||||
(node: any): void
|
|
||||||
current: null | number
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a lighterweight alternative to `useAnimatedRef()` for imperative UI thread actions.
|
|
||||||
// Render it like <View ref={ref} />, then pass `ref.current` to `measureHandle()` and such.
|
|
||||||
export function useHandleRef(): HandleRef {
|
|
||||||
return useState(() => {
|
|
||||||
const ref = (node: any) => {
|
|
||||||
if (node) {
|
|
||||||
ref.current =
|
|
||||||
node._nativeTag ??
|
|
||||||
node.__nativeTag ??
|
|
||||||
node.canonical?.nativeTag ??
|
|
||||||
null
|
|
||||||
} else {
|
|
||||||
ref.current = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ref.current = null
|
|
||||||
return ref
|
|
||||||
})[0] as HandleRef
|
|
||||||
}
|
|
||||||
|
|
||||||
// When using this version, you need to read ref.current on the JS thread, and pass it to UI.
|
|
||||||
export function measureHandle(
|
|
||||||
current: number | null,
|
|
||||||
): MeasuredDimensions | null {
|
|
||||||
'worklet'
|
|
||||||
if (current !== null) {
|
|
||||||
return measure((() => current) as AnimatedRef<any>)
|
|
||||||
} else {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +1,22 @@
|
|||||||
import React, {memo} from 'react'
|
import React, {memo} from 'react'
|
||||||
import {StyleSheet, TouchableWithoutFeedback, View} from 'react-native'
|
import {StyleSheet, TouchableWithoutFeedback, View} from 'react-native'
|
||||||
import {MeasuredDimensions, runOnJS, runOnUI} from 'react-native-reanimated'
|
import Animated, {
|
||||||
|
measure,
|
||||||
|
type MeasuredDimensions,
|
||||||
|
runOnJS,
|
||||||
|
runOnUI,
|
||||||
|
useAnimatedRef,
|
||||||
|
} from 'react-native-reanimated'
|
||||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
import {AppBskyActorDefs, ModerationDecision} from '@atproto/api'
|
import {type AppBskyActorDefs, type ModerationDecision} from '@atproto/api'
|
||||||
import {msg} from '@lingui/macro'
|
import {msg} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {useNavigation} from '@react-navigation/native'
|
import {useNavigation} from '@react-navigation/native'
|
||||||
|
|
||||||
import {BACK_HITSLOP} from '#/lib/constants'
|
import {BACK_HITSLOP} from '#/lib/constants'
|
||||||
import {measureHandle, useHandleRef} from '#/lib/hooks/useHandleRef'
|
import {type NavigationProp} from '#/lib/routes/types'
|
||||||
import {NavigationProp} from '#/lib/routes/types'
|
|
||||||
import {isIOS} from '#/platform/detection'
|
import {isIOS} from '#/platform/detection'
|
||||||
import {Shadow} from '#/state/cache/types'
|
import {type Shadow} from '#/state/cache/types'
|
||||||
import {useLightboxControls} from '#/state/lightbox'
|
import {useLightboxControls} from '#/state/lightbox'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
import {LoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder'
|
import {LoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder'
|
||||||
@@ -46,7 +51,7 @@ let ProfileHeaderShell = ({
|
|||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
const {top: topInset} = useSafeAreaInsets()
|
const {top: topInset} = useSafeAreaInsets()
|
||||||
|
|
||||||
const aviRef = useHandleRef()
|
const aviRef = useAnimatedRef()
|
||||||
|
|
||||||
const onPressBack = React.useCallback(() => {
|
const onPressBack = React.useCallback(() => {
|
||||||
if (navigation.canGoBack()) {
|
if (navigation.canGoBack()) {
|
||||||
@@ -83,10 +88,9 @@ let ProfileHeaderShell = ({
|
|||||||
const modui = moderation.ui('avatar')
|
const modui = moderation.ui('avatar')
|
||||||
const avatar = profile.avatar
|
const avatar = profile.avatar
|
||||||
if (avatar && !(modui.blur && modui.noOverride)) {
|
if (avatar && !(modui.blur && modui.noOverride)) {
|
||||||
const aviHandle = aviRef.current
|
|
||||||
runOnUI(() => {
|
runOnUI(() => {
|
||||||
'worklet'
|
'worklet'
|
||||||
const rect = measureHandle(aviHandle)
|
const rect = measure(aviRef)
|
||||||
runOnJS(_openLightbox)(avatar, rect)
|
runOnJS(_openLightbox)(avatar, rect)
|
||||||
})()
|
})()
|
||||||
}
|
}
|
||||||
@@ -174,14 +178,14 @@ let ProfileHeaderShell = ({
|
|||||||
styles.avi,
|
styles.avi,
|
||||||
profile.associated?.labeler && styles.aviLabeler,
|
profile.associated?.labeler && styles.aviLabeler,
|
||||||
]}>
|
]}>
|
||||||
<View ref={aviRef} collapsable={false}>
|
<Animated.View ref={aviRef} collapsable={false}>
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
type={profile.associated?.labeler ? 'labeler' : 'user'}
|
type={profile.associated?.labeler ? 'labeler' : 'user'}
|
||||||
size={90}
|
size={90}
|
||||||
avatar={profile.avatar}
|
avatar={profile.avatar}
|
||||||
moderation={moderation.ui('avatar')}
|
moderation={moderation.ui('avatar')}
|
||||||
/>
|
/>
|
||||||
</View>
|
</Animated.View>
|
||||||
</View>
|
</View>
|
||||||
</TouchableWithoutFeedback>
|
</TouchableWithoutFeedback>
|
||||||
</GrowableAvatar>
|
</GrowableAvatar>
|
||||||
|
|||||||
@@ -1,23 +1,28 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {Pressable, View} from 'react-native'
|
import {Pressable, View} from 'react-native'
|
||||||
import {MeasuredDimensions, runOnJS, runOnUI} from 'react-native-reanimated'
|
import Animated, {
|
||||||
import {AppBskyGraphDefs} from '@atproto/api'
|
measure,
|
||||||
|
type MeasuredDimensions,
|
||||||
|
runOnJS,
|
||||||
|
runOnUI,
|
||||||
|
useAnimatedRef,
|
||||||
|
} from 'react-native-reanimated'
|
||||||
|
import {type AppBskyGraphDefs} from '@atproto/api'
|
||||||
import {msg, Trans} from '@lingui/macro'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {useNavigation} from '@react-navigation/native'
|
import {useNavigation} from '@react-navigation/native'
|
||||||
|
|
||||||
import {measureHandle, useHandleRef} from '#/lib/hooks/useHandleRef'
|
|
||||||
import {usePalette} from '#/lib/hooks/usePalette'
|
import {usePalette} from '#/lib/hooks/usePalette'
|
||||||
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
|
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
|
||||||
import {makeProfileLink} from '#/lib/routes/links'
|
import {makeProfileLink} from '#/lib/routes/links'
|
||||||
import {NavigationProp} from '#/lib/routes/types'
|
import {type NavigationProp} from '#/lib/routes/types'
|
||||||
import {sanitizeHandle} from '#/lib/strings/handles'
|
import {sanitizeHandle} from '#/lib/strings/handles'
|
||||||
import {emitSoftReset} from '#/state/events'
|
import {emitSoftReset} from '#/state/events'
|
||||||
import {useLightboxControls} from '#/state/lightbox'
|
import {useLightboxControls} from '#/state/lightbox'
|
||||||
import {TextLink} from '#/view/com/util/Link'
|
import {TextLink} from '#/view/com/util/Link'
|
||||||
import {LoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder'
|
import {LoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder'
|
||||||
import {Text} from '#/view/com/util/text/Text'
|
import {Text} from '#/view/com/util/text/Text'
|
||||||
import {UserAvatar, UserAvatarType} from '#/view/com/util/UserAvatar'
|
import {UserAvatar, type UserAvatarType} from '#/view/com/util/UserAvatar'
|
||||||
import {StarterPack} from '#/components/icons/StarterPack'
|
import {StarterPack} from '#/components/icons/StarterPack'
|
||||||
import * as Layout from '#/components/Layout'
|
import * as Layout from '#/components/Layout'
|
||||||
|
|
||||||
@@ -52,7 +57,7 @@ export function ProfileSubpageHeader({
|
|||||||
const {openLightbox} = useLightboxControls()
|
const {openLightbox} = useLightboxControls()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const canGoBack = navigation.canGoBack()
|
const canGoBack = navigation.canGoBack()
|
||||||
const aviRef = useHandleRef()
|
const aviRef = useAnimatedRef()
|
||||||
|
|
||||||
const _openLightbox = React.useCallback(
|
const _openLightbox = React.useCallback(
|
||||||
(uri: string, thumbRect: MeasuredDimensions | null) => {
|
(uri: string, thumbRect: MeasuredDimensions | null) => {
|
||||||
@@ -81,10 +86,9 @@ export function ProfileSubpageHeader({
|
|||||||
if (
|
if (
|
||||||
avatar // TODO && !(view.moderation.avatar.blur && view.moderation.avatar.noOverride)
|
avatar // TODO && !(view.moderation.avatar.blur && view.moderation.avatar.noOverride)
|
||||||
) {
|
) {
|
||||||
const aviHandle = aviRef.current
|
|
||||||
runOnUI(() => {
|
runOnUI(() => {
|
||||||
'worklet'
|
'worklet'
|
||||||
const rect = measureHandle(aviHandle)
|
const rect = measure(aviRef)
|
||||||
runOnJS(_openLightbox)(avatar, rect)
|
runOnJS(_openLightbox)(avatar, rect)
|
||||||
})()
|
})()
|
||||||
}
|
}
|
||||||
@@ -111,7 +115,7 @@ export function ProfileSubpageHeader({
|
|||||||
paddingBottom: 14,
|
paddingBottom: 14,
|
||||||
paddingHorizontal: isMobile ? 12 : 14,
|
paddingHorizontal: isMobile ? 12 : 14,
|
||||||
}}>
|
}}>
|
||||||
<View ref={aviRef} collapsable={false}>
|
<Animated.View ref={aviRef} collapsable={false}>
|
||||||
<Pressable
|
<Pressable
|
||||||
testID="headerAviButton"
|
testID="headerAviButton"
|
||||||
onPress={onPressAvi}
|
onPress={onPressAvi}
|
||||||
@@ -125,7 +129,7 @@ export function ProfileSubpageHeader({
|
|||||||
<UserAvatar type={avatarType} size={58} avatar={avatar} />
|
<UserAvatar type={avatarType} size={58} avatar={avatar} />
|
||||||
)}
|
)}
|
||||||
</Pressable>
|
</Pressable>
|
||||||
</View>
|
</Animated.View>
|
||||||
<View style={{flex: 1, gap: 4}}>
|
<View style={{flex: 1, gap: 4}}>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<LoadingPlaceholder
|
<LoadingPlaceholder
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import React, {useRef} from 'react'
|
import React, {useRef} from 'react'
|
||||||
import {DimensionValue, Pressable, View} from 'react-native'
|
import {type DimensionValue, Pressable, View} from 'react-native'
|
||||||
|
import Animated, {type AnimatedRef, useAnimatedRef} from 'react-native-reanimated'
|
||||||
import {Image} from 'expo-image'
|
import {Image} from 'expo-image'
|
||||||
import {AppBskyEmbedImages} from '@atproto/api'
|
import {type AppBskyEmbedImages} from '@atproto/api'
|
||||||
import {msg} from '@lingui/macro'
|
import {msg} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {HandleRef, useHandleRef} from '#/lib/hooks/useHandleRef'
|
import {type Dimensions} from '#/lib/media/types'
|
||||||
import type {Dimensions} from '#/lib/media/types'
|
|
||||||
import {isNative} from '#/platform/detection'
|
import {isNative} from '#/platform/detection'
|
||||||
import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge'
|
import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge'
|
||||||
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
||||||
@@ -68,14 +68,17 @@ export function AutoSizedImage({
|
|||||||
image: AppBskyEmbedImages.ViewImage
|
image: AppBskyEmbedImages.ViewImage
|
||||||
crop?: 'none' | 'square' | 'constrained'
|
crop?: 'none' | 'square' | 'constrained'
|
||||||
hideBadge?: boolean
|
hideBadge?: boolean
|
||||||
onPress?: (containerRef: HandleRef, fetchedDims: Dimensions | null) => void
|
onPress?: (
|
||||||
|
containerRef: AnimatedRef<any>,
|
||||||
|
fetchedDims: Dimensions | null,
|
||||||
|
) => void
|
||||||
onLongPress?: () => void
|
onLongPress?: () => void
|
||||||
onPressIn?: () => void
|
onPressIn?: () => void
|
||||||
}) {
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const largeAlt = useLargeAltBadgeEnabled()
|
const largeAlt = useLargeAltBadgeEnabled()
|
||||||
const containerRef = useHandleRef()
|
const containerRef = useAnimatedRef()
|
||||||
const fetchedDimsRef = useRef<{width: number; height: number} | null>(null)
|
const fetchedDimsRef = useRef<{width: number; height: number} | null>(null)
|
||||||
|
|
||||||
let aspectRatio: number | undefined
|
let aspectRatio: number | undefined
|
||||||
@@ -103,7 +106,7 @@ export function AutoSizedImage({
|
|||||||
const hasAlt = !!image.alt
|
const hasAlt = !!image.alt
|
||||||
|
|
||||||
const contents = (
|
const contents = (
|
||||||
<View ref={containerRef} collapsable={false} style={{flex: 1}}>
|
<Animated.View ref={containerRef} collapsable={false} style={{flex: 1}}>
|
||||||
<Image
|
<Image
|
||||||
contentFit={isContain ? 'contain' : 'cover'}
|
contentFit={isContain ? 'contain' : 'cover'}
|
||||||
style={[a.w_full, a.h_full]}
|
style={[a.w_full, a.h_full]}
|
||||||
@@ -185,7 +188,7 @@ export function AutoSizedImage({
|
|||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
) : null}
|
) : null}
|
||||||
</View>
|
</Animated.View>
|
||||||
)
|
)
|
||||||
|
|
||||||
if (cropDisabled) {
|
if (cropDisabled) {
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import React from 'react'
|
import {Pressable, type StyleProp, View, type ViewStyle} from 'react-native'
|
||||||
import {Pressable, StyleProp, View, ViewStyle} from 'react-native'
|
import {type AnimatedRef} from 'react-native-reanimated'
|
||||||
import {Image, ImageStyle} from 'expo-image'
|
import {Image, type ImageStyle} from 'expo-image'
|
||||||
import {AppBskyEmbedImages} from '@atproto/api'
|
import {type AppBskyEmbedImages} from '@atproto/api'
|
||||||
import {msg} from '@lingui/macro'
|
import {msg} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
import type React from 'react'
|
||||||
|
|
||||||
import {HandleRef} from '#/lib/hooks/useHandleRef'
|
import {type Dimensions} from '#/lib/media/types'
|
||||||
import {Dimensions} from '#/lib/media/types'
|
|
||||||
import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge'
|
import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge'
|
||||||
import {PostEmbedViewContext} from '#/view/com/util/post-embeds/types'
|
import {PostEmbedViewContext} from '#/view/com/util/post-embeds/types'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
@@ -20,7 +20,7 @@ interface Props {
|
|||||||
index: number
|
index: number
|
||||||
onPress?: (
|
onPress?: (
|
||||||
index: number,
|
index: number,
|
||||||
containerRefs: HandleRef[],
|
containerRefs: AnimatedRef<any>[],
|
||||||
fetchedDims: (Dimensions | null)[],
|
fetchedDims: (Dimensions | null)[],
|
||||||
) => void
|
) => void
|
||||||
onLongPress?: EventFunction
|
onLongPress?: EventFunction
|
||||||
@@ -28,7 +28,7 @@ interface Props {
|
|||||||
imageStyle?: StyleProp<ImageStyle>
|
imageStyle?: StyleProp<ImageStyle>
|
||||||
viewContext?: PostEmbedViewContext
|
viewContext?: PostEmbedViewContext
|
||||||
insetBorderStyle?: StyleProp<ViewStyle>
|
insetBorderStyle?: StyleProp<ViewStyle>
|
||||||
containerRefs: HandleRef[]
|
containerRefs: AnimatedRef<any>[]
|
||||||
thumbDimsRef: React.MutableRefObject<(Dimensions | null)[]>
|
thumbDimsRef: React.MutableRefObject<(Dimensions | null)[]>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {StyleProp, StyleSheet, View, ViewStyle} from 'react-native'
|
import {type StyleProp, StyleSheet, View, type ViewStyle} from 'react-native'
|
||||||
import {AppBskyEmbedImages} from '@atproto/api'
|
import {type AnimatedRef, useAnimatedRef} from 'react-native-reanimated'
|
||||||
|
import {type AppBskyEmbedImages} from '@atproto/api'
|
||||||
|
|
||||||
import {HandleRef, useHandleRef} from '#/lib/hooks/useHandleRef'
|
|
||||||
import {PostEmbedViewContext} from '#/view/com/util/post-embeds/types'
|
import {PostEmbedViewContext} from '#/view/com/util/post-embeds/types'
|
||||||
import {atoms as a, useBreakpoints} from '#/alf'
|
import {atoms as a, useBreakpoints} from '#/alf'
|
||||||
import {Dimensions} from '../../lightbox/ImageViewing/@types'
|
import {type Dimensions} from '../../lightbox/ImageViewing/@types'
|
||||||
import {GalleryItem} from './Gallery'
|
import {GalleryItem} from './Gallery'
|
||||||
|
|
||||||
interface ImageLayoutGridProps {
|
interface ImageLayoutGridProps {
|
||||||
images: AppBskyEmbedImages.ViewImage[]
|
images: AppBskyEmbedImages.ViewImage[]
|
||||||
onPress?: (
|
onPress?: (
|
||||||
index: number,
|
index: number,
|
||||||
containerRefs: HandleRef[],
|
containerRefs: AnimatedRef<any>[],
|
||||||
fetchedDims: (Dimensions | null)[],
|
fetchedDims: (Dimensions | null)[],
|
||||||
) => void
|
) => void
|
||||||
onLongPress?: (index: number) => void
|
onLongPress?: (index: number) => void
|
||||||
@@ -43,7 +43,7 @@ interface ImageLayoutGridInnerProps {
|
|||||||
images: AppBskyEmbedImages.ViewImage[]
|
images: AppBskyEmbedImages.ViewImage[]
|
||||||
onPress?: (
|
onPress?: (
|
||||||
index: number,
|
index: number,
|
||||||
containerRefs: HandleRef[],
|
containerRefs: AnimatedRef<any>[],
|
||||||
fetchedDims: (Dimensions | null)[],
|
fetchedDims: (Dimensions | null)[],
|
||||||
) => void
|
) => void
|
||||||
onLongPress?: (index: number) => void
|
onLongPress?: (index: number) => void
|
||||||
@@ -56,10 +56,10 @@ function ImageLayoutGridInner(props: ImageLayoutGridInnerProps) {
|
|||||||
const gap = props.gap
|
const gap = props.gap
|
||||||
const count = props.images.length
|
const count = props.images.length
|
||||||
|
|
||||||
const containerRef1 = useHandleRef()
|
const containerRef1 = useAnimatedRef()
|
||||||
const containerRef2 = useHandleRef()
|
const containerRef2 = useAnimatedRef()
|
||||||
const containerRef3 = useHandleRef()
|
const containerRef3 = useAnimatedRef()
|
||||||
const containerRef4 = useHandleRef()
|
const containerRef4 = useAnimatedRef()
|
||||||
const thumbDimsRef = React.useRef<(Dimensions | null)[]>([])
|
const thumbDimsRef = React.useRef<(Dimensions | null)[]>([])
|
||||||
|
|
||||||
switch (count) {
|
switch (count) {
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {
|
import {
|
||||||
InteractionManager,
|
InteractionManager,
|
||||||
StyleProp,
|
type StyleProp,
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
View,
|
View,
|
||||||
ViewStyle,
|
type ViewStyle,
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import {MeasuredDimensions, runOnJS, runOnUI} from 'react-native-reanimated'
|
import {
|
||||||
|
type AnimatedRef,
|
||||||
|
measure,
|
||||||
|
type MeasuredDimensions,
|
||||||
|
runOnJS,
|
||||||
|
runOnUI,
|
||||||
|
} from 'react-native-reanimated'
|
||||||
import {Image} from 'expo-image'
|
import {Image} from 'expo-image'
|
||||||
import {
|
import {
|
||||||
AppBskyEmbedExternal,
|
AppBskyEmbedExternal,
|
||||||
@@ -18,10 +24,9 @@ import {
|
|||||||
AppBskyGraphDefs,
|
AppBskyGraphDefs,
|
||||||
moderateFeedGenerator,
|
moderateFeedGenerator,
|
||||||
moderateUserList,
|
moderateUserList,
|
||||||
ModerationDecision,
|
type ModerationDecision,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
|
|
||||||
import {HandleRef, measureHandle} from '#/lib/hooks/useHandleRef'
|
|
||||||
import {usePalette} from '#/lib/hooks/usePalette'
|
import {usePalette} from '#/lib/hooks/usePalette'
|
||||||
import {useLightboxControls} from '#/state/lightbox'
|
import {useLightboxControls} from '#/state/lightbox'
|
||||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||||
@@ -30,7 +35,7 @@ import {atoms as a, useTheme} from '#/alf'
|
|||||||
import * as ListCard from '#/components/ListCard'
|
import * as ListCard from '#/components/ListCard'
|
||||||
import {Embed as StarterPackCard} from '#/components/StarterPack/StarterPackCard'
|
import {Embed as StarterPackCard} from '#/components/StarterPack/StarterPackCard'
|
||||||
import {ContentHider} from '../../../../components/moderation/ContentHider'
|
import {ContentHider} from '../../../../components/moderation/ContentHider'
|
||||||
import {Dimensions} from '../../lightbox/ImageViewing/@types'
|
import {type Dimensions} from '../../lightbox/ImageViewing/@types'
|
||||||
import {AutoSizedImage} from '../images/AutoSizedImage'
|
import {AutoSizedImage} from '../images/AutoSizedImage'
|
||||||
import {ImageLayoutGrid} from '../images/ImageLayoutGrid'
|
import {ImageLayoutGrid} from '../images/ImageLayoutGrid'
|
||||||
import {ExternalLinkEmbed} from './ExternalLinkEmbed'
|
import {ExternalLinkEmbed} from './ExternalLinkEmbed'
|
||||||
@@ -158,13 +163,15 @@ export function PostEmbeds({
|
|||||||
}
|
}
|
||||||
const onPress = (
|
const onPress = (
|
||||||
index: number,
|
index: number,
|
||||||
refs: HandleRef[],
|
refs: AnimatedRef<any>[],
|
||||||
fetchedDims: (Dimensions | null)[],
|
fetchedDims: (Dimensions | null)[],
|
||||||
) => {
|
) => {
|
||||||
const handles = refs.map(r => r.current)
|
|
||||||
runOnUI(() => {
|
runOnUI(() => {
|
||||||
'worklet'
|
'worklet'
|
||||||
const rects = handles.map(measureHandle)
|
const rects: (MeasuredDimensions | null)[] = []
|
||||||
|
for (const r of refs) {
|
||||||
|
rects.push(measure(r))
|
||||||
|
}
|
||||||
runOnJS(_openLightbox)(index, rects, fetchedDims)
|
runOnJS(_openLightbox)(index, rects, fetchedDims)
|
||||||
})()
|
})()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3764,25 +3764,25 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.47.0.tgz#5478fdf443ff8158f9de171c704ae45308696c7d"
|
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.47.0.tgz#5478fdf443ff8158f9de171c704ae45308696c7d"
|
||||||
integrity sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==
|
integrity sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==
|
||||||
|
|
||||||
"@expo/cli@0.24.7":
|
"@expo/cli@0.24.8":
|
||||||
version "0.24.7"
|
version "0.24.8"
|
||||||
resolved "https://registry.yarnpkg.com/@expo/cli/-/cli-0.24.7.tgz#8a23cef63f9cb6a941e0cc231a4225702c48ee7a"
|
resolved "https://registry.yarnpkg.com/@expo/cli/-/cli-0.24.8.tgz#e341a3ffa755da7bd84fae1671a931d4ba4aaa5e"
|
||||||
integrity sha512-4KrDFzLNiLWHPOtRIIvSkS0m+4s5+fFPefe04hAf0bUDecrHmL0yZUPyz3At0XAR/eDRZJ/PeitAoA9DTWF2gw==
|
integrity sha512-LUr/Ofc8mFBKM9kQGn3t4aC9X0JDa54PyYL4gN2HU1XqXaj5pjdK5MZW2UFKnhgYI3tA9Gjt0s4ueRHX8FhKeA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@0no-co/graphql.web" "^1.0.8"
|
"@0no-co/graphql.web" "^1.0.8"
|
||||||
"@babel/runtime" "^7.20.0"
|
"@babel/runtime" "^7.20.0"
|
||||||
"@expo/code-signing-certificates" "^0.0.5"
|
"@expo/code-signing-certificates" "^0.0.5"
|
||||||
"@expo/config" "~11.0.5"
|
"@expo/config" "~11.0.6"
|
||||||
"@expo/config-plugins" "~9.1.7"
|
"@expo/config-plugins" "~10.0.0"
|
||||||
"@expo/devcert" "^1.1.2"
|
"@expo/devcert" "^1.1.2"
|
||||||
"@expo/env" "~1.0.4"
|
"@expo/env" "~1.0.4"
|
||||||
"@expo/image-utils" "^0.7.3"
|
"@expo/image-utils" "^0.7.3"
|
||||||
"@expo/json-file" "^9.1.3"
|
"@expo/json-file" "^9.1.3"
|
||||||
"@expo/metro-config" "~0.20.9"
|
"@expo/metro-config" "~0.20.10"
|
||||||
"@expo/osascript" "^2.2.3"
|
"@expo/osascript" "^2.2.3"
|
||||||
"@expo/package-manager" "^1.8.3"
|
"@expo/package-manager" "^1.8.3"
|
||||||
"@expo/plist" "^0.3.3"
|
"@expo/plist" "^0.3.3"
|
||||||
"@expo/prebuild-config" "^9.0.2"
|
"@expo/prebuild-config" "^9.0.3"
|
||||||
"@expo/spawn-async" "^1.7.2"
|
"@expo/spawn-async" "^1.7.2"
|
||||||
"@expo/ws-tunnel" "^1.0.1"
|
"@expo/ws-tunnel" "^1.0.1"
|
||||||
"@expo/xcpretty" "^4.3.0"
|
"@expo/xcpretty" "^4.3.0"
|
||||||
@@ -3879,6 +3879,26 @@
|
|||||||
xcode "^3.0.1"
|
xcode "^3.0.1"
|
||||||
xml2js "0.6.0"
|
xml2js "0.6.0"
|
||||||
|
|
||||||
|
"@expo/config-plugins@~10.0.0":
|
||||||
|
version "10.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-10.0.0.tgz#5ea58f9c12d1d06b6c43c9fb9e7163bb4954d04f"
|
||||||
|
integrity sha512-VAGMjQoBFKwyXGzVcAptqY68LGx1pZr8c+4e82h6E1elenjeVBt1CBaWHC/kiAw2Akr2nkdUVd85nIaC81m1ow==
|
||||||
|
dependencies:
|
||||||
|
"@expo/config-types" "^53.0.2"
|
||||||
|
"@expo/json-file" "~9.1.3"
|
||||||
|
"@expo/plist" "^0.3.3"
|
||||||
|
"@expo/sdk-runtime-versions" "^1.0.0"
|
||||||
|
chalk "^4.1.2"
|
||||||
|
debug "^4.3.5"
|
||||||
|
getenv "^1.0.0"
|
||||||
|
glob "^10.4.2"
|
||||||
|
resolve-from "^5.0.0"
|
||||||
|
semver "^7.5.4"
|
||||||
|
slash "^3.0.0"
|
||||||
|
slugify "^1.6.6"
|
||||||
|
xcode "^3.0.1"
|
||||||
|
xml2js "0.6.0"
|
||||||
|
|
||||||
"@expo/config-plugins@~9.0.10":
|
"@expo/config-plugins@~9.0.10":
|
||||||
version "9.0.10"
|
version "9.0.10"
|
||||||
resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-9.0.10.tgz#a25fd6061ea7f707213ff8344f562025f850fdc8"
|
resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-9.0.10.tgz#a25fd6061ea7f707213ff8344f562025f850fdc8"
|
||||||
@@ -3914,6 +3934,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-53.0.0.tgz#b08dbfe548e7762483dc9caf4c01592bec0051fd"
|
resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-53.0.0.tgz#b08dbfe548e7762483dc9caf4c01592bec0051fd"
|
||||||
integrity sha512-x94C0q6d8QzvBiEd/Tp9HbdRb5Q2hRgJwMRcvXA6Vsy970N/FdFx4NiOQk39WzxlNZhjn1YTz8JitysTJSOLSQ==
|
integrity sha512-x94C0q6d8QzvBiEd/Tp9HbdRb5Q2hRgJwMRcvXA6Vsy970N/FdFx4NiOQk39WzxlNZhjn1YTz8JitysTJSOLSQ==
|
||||||
|
|
||||||
|
"@expo/config-types@^53.0.2":
|
||||||
|
version "53.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-53.0.2.tgz#9251ddd56589e8f93703bfe7426d5daf120e4ec2"
|
||||||
|
integrity sha512-W7bmDvCjAnsaNlu9bJmaGm95AEFVfqS+qEnlEwfAFi4BwDf+eFWL5TM87iw6esKpglVF8J3nQ1zHI4+CeS9xrg==
|
||||||
|
|
||||||
"@expo/config@~10.0.4":
|
"@expo/config@~10.0.4":
|
||||||
version "10.0.5"
|
version "10.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/@expo/config/-/config-10.0.5.tgz#2de75e3f5d46a55f9f5140b73e0913265e6a41c6"
|
resolved "https://registry.yarnpkg.com/@expo/config/-/config-10.0.5.tgz#2de75e3f5d46a55f9f5140b73e0913265e6a41c6"
|
||||||
@@ -3952,6 +3977,25 @@
|
|||||||
slugify "^1.3.4"
|
slugify "^1.3.4"
|
||||||
sucrase "3.35.0"
|
sucrase "3.35.0"
|
||||||
|
|
||||||
|
"@expo/config@~11.0.6":
|
||||||
|
version "11.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@expo/config/-/config-11.0.6.tgz#934efecf3393e0d47d00cadd511095b2255c3262"
|
||||||
|
integrity sha512-lmBP4kbNFiDLZoxPNuaN/UanFzns0+PxJA1eimOAHa6aFSAHTl48AHozbJ6UARbvig/TVTzLfGpoxv2Ih03iYQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/code-frame" "~7.10.4"
|
||||||
|
"@expo/config-plugins" "~10.0.0"
|
||||||
|
"@expo/config-types" "^53.0.2"
|
||||||
|
"@expo/json-file" "^9.1.3"
|
||||||
|
deepmerge "^4.3.1"
|
||||||
|
getenv "^1.0.0"
|
||||||
|
glob "^10.4.2"
|
||||||
|
require-from-string "^2.0.2"
|
||||||
|
resolve-from "^5.0.0"
|
||||||
|
resolve-workspace-root "^2.0.0"
|
||||||
|
semver "^7.6.0"
|
||||||
|
slugify "^1.3.4"
|
||||||
|
sucrase "3.35.0"
|
||||||
|
|
||||||
"@expo/devcert@^1.1.2":
|
"@expo/devcert@^1.1.2":
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/@expo/devcert/-/devcert-1.1.2.tgz#a4923b8ea5b34fde31d6e006a40d0f594096a0ed"
|
resolved "https://registry.yarnpkg.com/@expo/devcert/-/devcert-1.1.2.tgz#a4923b8ea5b34fde31d6e006a40d0f594096a0ed"
|
||||||
@@ -4056,16 +4100,16 @@
|
|||||||
json5 "^2.2.3"
|
json5 "^2.2.3"
|
||||||
write-file-atomic "^2.3.0"
|
write-file-atomic "^2.3.0"
|
||||||
|
|
||||||
"@expo/metro-config@0.20.9", "@expo/metro-config@~0.20.9":
|
"@expo/metro-config@0.20.10", "@expo/metro-config@~0.20.10":
|
||||||
version "0.20.9"
|
version "0.20.10"
|
||||||
resolved "https://registry.yarnpkg.com/@expo/metro-config/-/metro-config-0.20.9.tgz#a71e6dbb6ec0b6c765f70e186695b65c25332868"
|
resolved "https://registry.yarnpkg.com/@expo/metro-config/-/metro-config-0.20.10.tgz#ffe3a5bbbe64b077d89a6a422196a6257dabb46a"
|
||||||
integrity sha512-OYoS/w19Opc0LftX5J6XY6KrdfGqKwahNM44NKh4YzgjBHSsr2kM6E318FAP5fdgVOgPf1INB+XuKCzcNNJ9cw==
|
integrity sha512-bD2NJUOhrWRj3ChL8Z+UCXMncbL6DYhmQA1nyGsi74vlZ7ojrN9437/F6Z/RsryifQ7b2cR1LiSw2oerxc30GQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/core" "^7.20.0"
|
"@babel/core" "^7.20.0"
|
||||||
"@babel/generator" "^7.20.5"
|
"@babel/generator" "^7.20.5"
|
||||||
"@babel/parser" "^7.20.0"
|
"@babel/parser" "^7.20.0"
|
||||||
"@babel/types" "^7.20.0"
|
"@babel/types" "^7.20.0"
|
||||||
"@expo/config" "~11.0.5"
|
"@expo/config" "~11.0.6"
|
||||||
"@expo/env" "~1.0.4"
|
"@expo/env" "~1.0.4"
|
||||||
"@expo/json-file" "~9.1.3"
|
"@expo/json-file" "~9.1.3"
|
||||||
"@expo/spawn-async" "^1.7.2"
|
"@expo/spawn-async" "^1.7.2"
|
||||||
@@ -4144,6 +4188,22 @@
|
|||||||
semver "^7.6.0"
|
semver "^7.6.0"
|
||||||
xml2js "0.6.0"
|
xml2js "0.6.0"
|
||||||
|
|
||||||
|
"@expo/prebuild-config@^9.0.3":
|
||||||
|
version "9.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@expo/prebuild-config/-/prebuild-config-9.0.3.tgz#28fae76590a49d7811569951663e4f112e834fa2"
|
||||||
|
integrity sha512-mopn+uMJTDbNOdIB5wpgha64qnz9LYk/REA0A6k93gxsUIi1/tiKznAM53bQ/H/AfL3njI28s2+YWGTX7Jo5JA==
|
||||||
|
dependencies:
|
||||||
|
"@expo/config" "~11.0.6"
|
||||||
|
"@expo/config-plugins" "~10.0.0"
|
||||||
|
"@expo/config-types" "^53.0.2"
|
||||||
|
"@expo/image-utils" "^0.7.3"
|
||||||
|
"@expo/json-file" "^9.1.3"
|
||||||
|
"@react-native/normalize-colors" "0.79.1"
|
||||||
|
debug "^4.3.1"
|
||||||
|
resolve-from "^5.0.0"
|
||||||
|
semver "^7.6.0"
|
||||||
|
xml2js "0.6.0"
|
||||||
|
|
||||||
"@expo/sdk-runtime-versions@^1.0.0":
|
"@expo/sdk-runtime-versions@^1.0.0":
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@expo/sdk-runtime-versions/-/sdk-runtime-versions-1.0.0.tgz#d7ebd21b19f1c6b0395e50d78da4416941c57f7c"
|
resolved "https://registry.yarnpkg.com/@expo/sdk-runtime-versions/-/sdk-runtime-versions-1.0.0.tgz#d7ebd21b19f1c6b0395e50d78da4416941c57f7c"
|
||||||
@@ -8710,10 +8770,10 @@ babel-preset-expo@~13.0.0:
|
|||||||
react-refresh "^0.14.2"
|
react-refresh "^0.14.2"
|
||||||
resolve-from "^5.0.0"
|
resolve-from "^5.0.0"
|
||||||
|
|
||||||
babel-preset-expo@~13.1.8:
|
babel-preset-expo@~13.1.9:
|
||||||
version "13.1.8"
|
version "13.1.9"
|
||||||
resolved "https://registry.yarnpkg.com/babel-preset-expo/-/babel-preset-expo-13.1.8.tgz#e2b0576c49118e853e4d32ffc92cf649749c3ea3"
|
resolved "https://registry.yarnpkg.com/babel-preset-expo/-/babel-preset-expo-13.1.9.tgz#0a4ad2e8e9deb94ece0ae5fd0d86b4fc1fccef2b"
|
||||||
integrity sha512-ZbQUeNYYCH95kDk9aOLTNOip5qXsSVa/RupJa92/ltenP/IWBG8y4AgzFCkNLagqTv/oEhBItKJKv+0Wzfbo3w==
|
integrity sha512-a5ocVi1v6zsh52ifTptQ9XgZupj1l2L3urWyuCZnHsIJhNNjhtjAgqEeQEWuH30d9rY8Xi1puSkwiThUSWFvrg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-module-imports" "^7.25.9"
|
"@babel/helper-module-imports" "^7.25.9"
|
||||||
"@babel/plugin-proposal-decorators" "^7.12.9"
|
"@babel/plugin-proposal-decorators" "^7.12.9"
|
||||||
@@ -11450,19 +11510,19 @@ expo-web-browser@~14.1.5:
|
|||||||
resolved "https://registry.yarnpkg.com/expo-web-browser/-/expo-web-browser-14.1.5.tgz#1f36c3c6d89a51cb669e4597231dc3490cb81dbd"
|
resolved "https://registry.yarnpkg.com/expo-web-browser/-/expo-web-browser-14.1.5.tgz#1f36c3c6d89a51cb669e4597231dc3490cb81dbd"
|
||||||
integrity sha512-SNKjWwLzpXLH+JwGyUI0FX5kIdn0vS+taJafRtRIWuFz3lPjQ8xaCI6AXVPhDne8Eb32++RxCZZCKX1dTuM+CA==
|
integrity sha512-SNKjWwLzpXLH+JwGyUI0FX5kIdn0vS+taJafRtRIWuFz3lPjQ8xaCI6AXVPhDne8Eb32++RxCZZCKX1dTuM+CA==
|
||||||
|
|
||||||
expo@53.0.1:
|
expo@53.0.2:
|
||||||
version "53.0.1"
|
version "53.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/expo/-/expo-53.0.1.tgz#ebcc71f1c4b4a98b45f4d65296ea7e4f4fe3c00c"
|
resolved "https://registry.yarnpkg.com/expo/-/expo-53.0.2.tgz#c2fd97f0fefedad3d04401cf3a97375a97f79514"
|
||||||
integrity sha512-qvqEJq4qDmyntXn1tjTDUc5MdD7/bVkKkkUpaTacE1Y/7s3zQia5xVeVOKDWWXsVC1mCjJbjy5/OPEOR4dGeVw==
|
integrity sha512-AF4wVTICFKyEIwJ71aq8ZZ0zpH4GcBm1hZO5ZzrWW7VXEE627hQb+3tZKYrKl0trDmov/z1fnz3QTZLcSPUAPg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.20.0"
|
"@babel/runtime" "^7.20.0"
|
||||||
"@expo/cli" "0.24.7"
|
"@expo/cli" "0.24.8"
|
||||||
"@expo/config" "~11.0.5"
|
"@expo/config" "~11.0.6"
|
||||||
"@expo/config-plugins" "~9.1.7"
|
"@expo/config-plugins" "~10.0.0"
|
||||||
"@expo/fingerprint" "0.12.3"
|
"@expo/fingerprint" "0.12.3"
|
||||||
"@expo/metro-config" "0.20.9"
|
"@expo/metro-config" "0.20.10"
|
||||||
"@expo/vector-icons" "^14.0.0"
|
"@expo/vector-icons" "^14.0.0"
|
||||||
babel-preset-expo "~13.1.8"
|
babel-preset-expo "~13.1.9"
|
||||||
expo-asset "~11.1.3"
|
expo-asset "~11.1.3"
|
||||||
expo-constants "~17.1.3"
|
expo-constants "~17.1.3"
|
||||||
expo-file-system "~18.1.7"
|
expo-file-system "~18.1.7"
|
||||||
|
|||||||
Reference in New Issue
Block a user