about summary refs log tree commit diff
path: root/src/components/dms/EmojiReactionPicker.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/dms/EmojiReactionPicker.tsx')
-rw-r--r--src/components/dms/EmojiReactionPicker.tsx118
1 files changed, 118 insertions, 0 deletions
diff --git a/src/components/dms/EmojiReactionPicker.tsx b/src/components/dms/EmojiReactionPicker.tsx
new file mode 100644
index 000000000..a98cebf9a
--- /dev/null
+++ b/src/components/dms/EmojiReactionPicker.tsx
@@ -0,0 +1,118 @@
+import {useMemo, useState} from 'react'
+import {Alert, useWindowDimensions, View} from 'react-native'
+import {type ChatBskyConvoDefs} from '@atproto/api'
+import {msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+
+import {useSession} from '#/state/session'
+import {atoms as a, tokens, useTheme} from '#/alf'
+import * as ContextMenu from '#/components/ContextMenu'
+import {
+  useContextMenuContext,
+  useContextMenuMenuContext,
+} from '#/components/ContextMenu/context'
+import {
+  EmojiHeartEyes_Stroke2_Corner0_Rounded as EmojiHeartEyesIcon,
+  EmojiSmile_Stroke2_Corner0_Rounded as EmojiSmileIcon,
+} from '#/components/icons/Emoji'
+import {type TriggerProps} from '#/components/Menu/types'
+import {Text} from '#/components/Typography'
+import {EmojiPopup} from './EmojiPopup'
+
+export function EmojiReactionPicker({
+  message,
+}: {
+  message: ChatBskyConvoDefs.MessageView
+  children?: TriggerProps['children']
+}) {
+  const {_} = useLingui()
+  const {currentAccount} = useSession()
+  const t = useTheme()
+  const isFromSelf = message.sender?.did === currentAccount?.did
+  const {measurement, close} = useContextMenuContext()
+  const {align} = useContextMenuMenuContext()
+  const [layout, setLayout] = useState({width: 0, height: 0})
+  const {width: screenWidth} = useWindowDimensions()
+
+  // 1 in 100 chance of showing heart eyes icon
+  const EmojiIcon = useMemo(() => {
+    return Math.random() < 0.01 ? EmojiHeartEyesIcon : EmojiSmileIcon
+  }, [])
+
+  const handleEmojiSelect = (emoji: string) => {
+    Alert.alert(emoji)
+  }
+
+  const position = useMemo(() => {
+    return {
+      x: align === 'left' ? 12 : screenWidth - layout.width - 12,
+      y: (measurement?.y ?? 0) - tokens.space.xs - layout.height,
+      height: layout.height,
+      width: layout.width,
+    }
+  }, [measurement, align, screenWidth, layout])
+
+  return (
+    <View
+      onLayout={evt => setLayout(evt.nativeEvent.layout)}
+      style={[
+        a.rounded_full,
+        a.absolute,
+        {bottom: '100%'},
+        isFromSelf ? a.right_0 : a.left_0,
+        t.scheme === 'light' ? t.atoms.bg : t.atoms.bg_contrast_25,
+        a.flex_row,
+        a.p_xs,
+        a.gap_xs,
+        a.mb_xs,
+        a.z_20,
+        a.border,
+        t.atoms.border_contrast_low,
+        a.shadow_md,
+      ]}>
+      {['👍', '😆', '❤️', '👀', '😢'].map(emoji => (
+        <ContextMenu.Item
+          position={position}
+          label={_(msg`React with ${emoji}`)}
+          key={emoji}
+          onPress={() => handleEmojiSelect(emoji)}
+          unstyled>
+          {hovered => (
+            <View
+              style={[
+                a.rounded_full,
+                hovered && {backgroundColor: t.palette.primary_500},
+                {height: 40, width: 40},
+                a.justify_center,
+                a.align_center,
+              ]}>
+              <Text style={[a.text_center, {fontSize: 30}]} emoji>
+                {emoji}
+              </Text>
+            </View>
+          )}
+        </ContextMenu.Item>
+      ))}
+      <EmojiPopup
+        onEmojiSelected={emoji => {
+          close()
+          handleEmojiSelect(emoji)
+        }}>
+        <View
+          style={[
+            a.rounded_full,
+            t.scheme === 'light'
+              ? t.atoms.bg_contrast_25
+              : t.atoms.bg_contrast_50,
+            {height: 40, width: 40},
+            a.justify_center,
+            a.align_center,
+            a.border,
+            t.atoms.border_contrast_low,
+          ]}>
+          <EmojiIcon size="xl" fill={t.palette.contrast_400} />
+        </View>
+      </EmojiPopup>
+    </View>
+  )
+}