Measure avi rects too

This commit is contained in:
Dan Abramov
2024-11-07 02:07:47 +00:00
parent a3b037af5c
commit d7fa2132bb
4 changed files with 85 additions and 36 deletions
+35 -13
View File
@@ -1,5 +1,12 @@
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 Animated, {
measure,
MeasuredDimensions,
runOnJS,
runOnUI,
useAnimatedRef,
} from 'react-native-reanimated'
import {AppBskyActorDefs, ModerationDecision} from '@atproto/api' import {AppBskyActorDefs, ModerationDecision} from '@atproto/api'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {msg} from '@lingui/macro' import {msg} from '@lingui/macro'
@@ -42,6 +49,7 @@ let ProfileHeaderShell = ({
const {openLightbox} = useLightboxControls() const {openLightbox} = useLightboxControls()
const navigation = useNavigation<NavigationProp>() const navigation = useNavigation<NavigationProp>()
const {isDesktop} = useWebMediaQueries() const {isDesktop} = useWebMediaQueries()
const aviRef = useAnimatedRef()
const onPressBack = React.useCallback(() => { const onPressBack = React.useCallback(() => {
if (navigation.canGoBack()) { if (navigation.canGoBack()) {
@@ -51,15 +59,14 @@ let ProfileHeaderShell = ({
} }
}, [navigation]) }, [navigation])
const onPressAvi = React.useCallback(() => { const _openLightbox = React.useCallback(
const modui = moderation.ui('avatar') (uri: string, thumbRect: MeasuredDimensions | null) => {
if (profile.avatar && !(modui.blur && modui.noOverride)) {
openLightbox({ openLightbox({
images: [ images: [
{ {
uri: profile.avatar, uri,
thumbUri: profile.avatar, thumbUri: uri,
thumbRect: null, thumbRect,
dimensions: { dimensions: {
// It's fine if it's actually smaller but we know it's 1:1. // It's fine if it's actually smaller but we know it's 1:1.
height: 1000, height: 1000,
@@ -70,8 +77,21 @@ let ProfileHeaderShell = ({
], ],
index: 0, index: 0,
}) })
},
[openLightbox],
)
const onPressAvi = React.useCallback(() => {
const modui = moderation.ui('avatar')
const avatar = profile.avatar
if (avatar && !(modui.blur && modui.noOverride)) {
runOnUI(() => {
'worklet'
const rect = measure(aviRef)
runOnJS(_openLightbox)(avatar, rect)
})()
} }
}, [openLightbox, profile, moderation]) }, [profile, moderation, _openLightbox, aviRef])
const isMe = React.useMemo( const isMe = React.useMemo(
() => currentAccount?.did === profile.did, () => currentAccount?.did === profile.did,
@@ -149,12 +169,14 @@ let ProfileHeaderShell = ({
styles.avi, styles.avi,
profile.associated?.labeler && styles.aviLabeler, profile.associated?.labeler && styles.aviLabeler,
]}> ]}>
<UserAvatar <Animated.View ref={aviRef} collapsable={false}>
type={profile.associated?.labeler ? 'labeler' : 'user'} <UserAvatar
size={90} type={profile.associated?.labeler ? 'labeler' : 'user'}
avatar={profile.avatar} size={90}
moderation={moderation.ui('avatar')} avatar={profile.avatar}
/> moderation={moderation.ui('avatar')}
/>
</Animated.View>
</View> </View>
</TouchableWithoutFeedback> </TouchableWithoutFeedback>
</GrowableAvatar> </GrowableAvatar>
+42 -21
View File
@@ -1,5 +1,12 @@
import React from 'react' import React from 'react'
import {Pressable, StyleSheet, View} from 'react-native' import {Pressable, StyleSheet, View} from 'react-native'
import Animated, {
measure,
MeasuredDimensions,
runOnJS,
runOnUI,
useAnimatedRef,
} from 'react-native-reanimated'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {msg, Trans} from '@lingui/macro' import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
@@ -53,6 +60,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 = useAnimatedRef()
const onPressBack = React.useCallback(() => { const onPressBack = React.useCallback(() => {
if (navigation.canGoBack()) { if (navigation.canGoBack()) {
@@ -66,16 +74,14 @@ export function ProfileSubpageHeader({
setDrawerOpen(true) setDrawerOpen(true)
}, [setDrawerOpen]) }, [setDrawerOpen])
const onPressAvi = React.useCallback(() => { const _openLightbox = React.useCallback(
if ( (uri: string, thumbRect: MeasuredDimensions | null) => {
avatar // TODO && !(view.moderation.avatar.blur && view.moderation.avatar.noOverride)
) {
openLightbox({ openLightbox({
images: [ images: [
{ {
uri: avatar, uri,
thumbUri: avatar, thumbUri: uri,
thumbRect: null, thumbRect,
dimensions: { dimensions: {
// It's fine if it's actually smaller but we know it's 1:1. // It's fine if it's actually smaller but we know it's 1:1.
height: 1000, height: 1000,
@@ -86,8 +92,21 @@ export function ProfileSubpageHeader({
], ],
index: 0, index: 0,
}) })
},
[openLightbox],
)
const onPressAvi = React.useCallback(() => {
if (
avatar // TODO && !(view.moderation.avatar.blur && view.moderation.avatar.noOverride)
) {
runOnUI(() => {
'worklet'
const rect = measure(aviRef)
runOnJS(_openLightbox)(avatar, rect)
})()
} }
}, [openLightbox, avatar]) }, [_openLightbox, avatar, aviRef])
return ( return (
<CenteredView style={pal.view}> <CenteredView style={pal.view}>
@@ -135,19 +154,21 @@ export function ProfileSubpageHeader({
paddingBottom: 6, paddingBottom: 6,
paddingHorizontal: isMobile ? 12 : 14, paddingHorizontal: isMobile ? 12 : 14,
}}> }}>
<Pressable <Animated.View ref={aviRef} collapsable={false}>
testID="headerAviButton" <Pressable
onPress={onPressAvi} testID="headerAviButton"
accessibilityRole="image" onPress={onPressAvi}
accessibilityLabel={_(msg`View the avatar`)} accessibilityRole="image"
accessibilityHint="" accessibilityLabel={_(msg`View the avatar`)}
style={{width: 58}}> accessibilityHint=""
{avatarType === 'starter-pack' ? ( style={{width: 58}}>
<StarterPack width={58} gradient="sky" /> {avatarType === 'starter-pack' ? (
) : ( <StarterPack width={58} gradient="sky" />
<UserAvatar type={avatarType} size={58} avatar={avatar} /> ) : (
)} <UserAvatar type={avatarType} size={58} avatar={avatar} />
</Pressable> )}
</Pressable>
</Animated.View>
<View style={{flex: 1}}> <View style={{flex: 1}}>
{isLoading ? ( {isLoading ? (
<LoadingPlaceholder <LoadingPlaceholder
+4 -1
View File
@@ -48,7 +48,10 @@ export function GalleryItem({
const hideBadges = const hideBadges =
viewContext === PostEmbedViewContext.FeedEmbedRecordWithMedia viewContext === PostEmbedViewContext.FeedEmbedRecordWithMedia
return ( return (
<Animated.View style={a.flex_1} ref={containerRefs[index]}> <Animated.View
style={a.flex_1}
ref={containerRefs[index]}
collapsable={false}>
<Pressable <Pressable
onPress={onPress ? () => onPress(index, containerRefs) : undefined} onPress={onPress ? () => onPress(index, containerRefs) : undefined}
onPressIn={onPressIn ? () => onPressIn(index) : undefined} onPressIn={onPressIn ? () => onPressIn(index) : undefined}
+4 -1
View File
@@ -180,7 +180,10 @@ export function PostEmbeds({
const image = images[0] const image = images[0]
return ( return (
<ContentHider modui={moderation?.ui('contentMedia')}> <ContentHider modui={moderation?.ui('contentMedia')}>
<Animated.View ref={containerRef} style={[a.mt_sm, style]}> <Animated.View
ref={containerRef}
collapsable={false}
style={[a.mt_sm, style]}>
<AutoSizedImage <AutoSizedImage
crop={ crop={
viewContext === PostEmbedViewContext.ThreadHighlighted viewContext === PostEmbedViewContext.ThreadHighlighted