about summary refs log tree commit diff
path: root/src/components/dms/NewMessagesPill.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/dms/NewMessagesPill.tsx')
-rw-r--r--src/components/dms/NewMessagesPill.tsx100
1 files changed, 75 insertions, 25 deletions
diff --git a/src/components/dms/NewMessagesPill.tsx b/src/components/dms/NewMessagesPill.tsx
index 4a0ba22c9..924f7c455 100644
--- a/src/components/dms/NewMessagesPill.tsx
+++ b/src/components/dms/NewMessagesPill.tsx
@@ -1,47 +1,97 @@
 import React from 'react'
-import {View} from 'react-native'
-import Animated from 'react-native-reanimated'
+import {Pressable, View} from 'react-native'
+import Animated, {
+  runOnJS,
+  useAnimatedStyle,
+  useSharedValue,
+  withTiming,
+} from 'react-native-reanimated'
+import {useSafeAreaInsets} from 'react-native-safe-area-context'
 import {Trans} from '@lingui/macro'
 
 import {
   ScaleAndFadeIn,
   ScaleAndFadeOut,
 } from 'lib/custom-animations/ScaleAndFade'
+import {useHaptics} from 'lib/haptics'
+import {isAndroid, isIOS, isWeb} from 'platform/detection'
 import {atoms as a, useTheme} from '#/alf'
 import {Text} from '#/components/Typography'
 
-export function NewMessagesPill() {
+const AnimatedPressable = Animated.createAnimatedComponent(Pressable)
+
+export function NewMessagesPill({
+  onPress: onPressInner,
+}: {
+  onPress: () => void
+}) {
   const t = useTheme()
+  const playHaptic = useHaptics()
+  const {bottom: bottomInset} = useSafeAreaInsets()
+  const bottomBarHeight = isIOS ? 42 : isAndroid ? 60 : 0
+  const bottomOffset = isWeb ? 0 : bottomInset + bottomBarHeight
+
+  const scale = useSharedValue(1)
+
+  const onPressIn = React.useCallback(() => {
+    if (isWeb) return
+    scale.value = withTiming(1.075, {duration: 100})
+  }, [scale])
+
+  const onPressOut = React.useCallback(() => {
+    if (isWeb) return
+    scale.value = withTiming(1, {duration: 100})
+  }, [scale])
+
+  const onPress = React.useCallback(() => {
+    runOnJS(playHaptic)()
+    onPressInner?.()
+  }, [onPressInner, playHaptic])
 
-  React.useEffect(() => {}, [])
+  const animatedStyle = useAnimatedStyle(() => ({
+    transform: [{scale: scale.value}],
+  }))
 
   return (
-    <Animated.View
+    <View
       style={[
-        a.py_sm,
-        a.rounded_full,
-        a.shadow_sm,
-        a.border,
-        t.atoms.bg_contrast_50,
-        t.atoms.border_contrast_medium,
+        a.absolute,
+        a.w_full,
+        a.z_10,
+        a.align_center,
         {
-          position: 'absolute',
-          bottom: 70,
-          width: '40%',
-          left: '30%',
-          alignItems: 'center',
-          shadowOpacity: 0.125,
-          shadowRadius: 12,
-          shadowOffset: {width: 0, height: 5},
+          bottom: bottomOffset + 70,
+          // Don't prevent scrolling in this area _except_ for in the pill itself
+          pointerEvents: 'box-none',
         },
-      ]}
-      entering={ScaleAndFadeIn}
-      exiting={ScaleAndFadeOut}>
-      <View style={{flex: 1}}>
+      ]}>
+      <AnimatedPressable
+        style={[
+          a.py_sm,
+          a.rounded_full,
+          a.shadow_sm,
+          a.border,
+          t.atoms.bg_contrast_50,
+          t.atoms.border_contrast_medium,
+          {
+            width: 160,
+            alignItems: 'center',
+            shadowOpacity: 0.125,
+            shadowRadius: 12,
+            shadowOffset: {width: 0, height: 5},
+            pointerEvents: 'box-only',
+          },
+          animatedStyle,
+        ]}
+        entering={ScaleAndFadeIn}
+        exiting={ScaleAndFadeOut}
+        onPress={onPress}
+        onPressIn={onPressIn}
+        onPressOut={onPressOut}>
         <Text style={[a.font_bold]}>
           <Trans>New messages</Trans>
         </Text>
-      </View>
-    </Animated.View>
+      </AnimatedPressable>
+    </View>
   )
 }