about summary refs log tree commit diff
path: root/src/view/com/profile/ProfileSubpageHeader.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/com/profile/ProfileSubpageHeader.tsx')
-rw-r--r--src/view/com/profile/ProfileSubpageHeader.tsx63
1 files changed, 42 insertions, 21 deletions
diff --git a/src/view/com/profile/ProfileSubpageHeader.tsx b/src/view/com/profile/ProfileSubpageHeader.tsx
index 5208224c5..13d14ec50 100644
--- a/src/view/com/profile/ProfileSubpageHeader.tsx
+++ b/src/view/com/profile/ProfileSubpageHeader.tsx
@@ -1,5 +1,12 @@
 import React from 'react'
 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 {msg, Trans} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
@@ -53,6 +60,7 @@ export function ProfileSubpageHeader({
   const {openLightbox} = useLightboxControls()
   const pal = usePalette('default')
   const canGoBack = navigation.canGoBack()
+  const aviRef = useAnimatedRef()
 
   const onPressBack = React.useCallback(() => {
     if (navigation.canGoBack()) {
@@ -66,15 +74,14 @@ export function ProfileSubpageHeader({
     setDrawerOpen(true)
   }, [setDrawerOpen])
 
-  const onPressAvi = React.useCallback(() => {
-    if (
-      avatar // TODO && !(view.moderation.avatar.blur && view.moderation.avatar.noOverride)
-    ) {
+  const _openLightbox = React.useCallback(
+    (uri: string, thumbRect: MeasuredDimensions | null) => {
       openLightbox({
         images: [
           {
-            uri: avatar,
-            thumbUri: avatar,
+            uri,
+            thumbUri: uri,
+            thumbRect,
             dimensions: {
               // It's fine if it's actually smaller but we know it's 1:1.
               height: 1000,
@@ -84,10 +91,22 @@ export function ProfileSubpageHeader({
           },
         ],
         index: 0,
-        thumbDims: null,
       })
+    },
+    [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 (
     <CenteredView style={pal.view}>
@@ -135,19 +154,21 @@ export function ProfileSubpageHeader({
           paddingBottom: 6,
           paddingHorizontal: isMobile ? 12 : 14,
         }}>
-        <Pressable
-          testID="headerAviButton"
-          onPress={onPressAvi}
-          accessibilityRole="image"
-          accessibilityLabel={_(msg`View the avatar`)}
-          accessibilityHint=""
-          style={{width: 58}}>
-          {avatarType === 'starter-pack' ? (
-            <StarterPack width={58} gradient="sky" />
-          ) : (
-            <UserAvatar type={avatarType} size={58} avatar={avatar} />
-          )}
-        </Pressable>
+        <Animated.View ref={aviRef} collapsable={false}>
+          <Pressable
+            testID="headerAviButton"
+            onPress={onPressAvi}
+            accessibilityRole="image"
+            accessibilityLabel={_(msg`View the avatar`)}
+            accessibilityHint=""
+            style={{width: 58}}>
+            {avatarType === 'starter-pack' ? (
+              <StarterPack width={58} gradient="sky" />
+            ) : (
+              <UserAvatar type={avatarType} size={58} avatar={avatar} />
+            )}
+          </Pressable>
+        </Animated.View>
         <View style={{flex: 1}}>
           {isLoading ? (
             <LoadingPlaceholder