about summary refs log tree commit diff
path: root/src/components/dms/ActionsWrapper.web.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/dms/ActionsWrapper.web.tsx')
-rw-r--r--src/components/dms/ActionsWrapper.web.tsx86
1 files changed, 86 insertions, 0 deletions
diff --git a/src/components/dms/ActionsWrapper.web.tsx b/src/components/dms/ActionsWrapper.web.tsx
new file mode 100644
index 000000000..f4c85ab94
--- /dev/null
+++ b/src/components/dms/ActionsWrapper.web.tsx
@@ -0,0 +1,86 @@
+import React from 'react'
+import {StyleSheet, View} from 'react-native'
+import {ChatBskyConvoDefs} from '@atproto-labs/api'
+
+import {atoms as a} from '#/alf'
+import {MessageMenu} from '#/components/dms/MessageMenu'
+import {useMenuControl} from '#/components/Menu'
+
+export function ActionsWrapper({
+  message,
+  isFromSelf,
+  children,
+}: {
+  message: ChatBskyConvoDefs.MessageView
+  isFromSelf: boolean
+  children: React.ReactNode
+}) {
+  const menuControl = useMenuControl()
+  const viewRef = React.useRef(null)
+
+  const [showActions, setShowActions] = React.useState(false)
+
+  const onMouseEnter = React.useCallback(() => {
+    setShowActions(true)
+  }, [])
+
+  const onMouseLeave = React.useCallback(() => {
+    setShowActions(false)
+  }, [])
+
+  // We need to handle the `onFocus` separately because we want to know if there is a related target (the element
+  // that is losing focus). If there isn't that means the focus is coming from a dropdown that is now closed.
+  const onFocus = React.useCallback<React.FocusEventHandler>(e => {
+    if (e.nativeEvent.relatedTarget == null) return
+    setShowActions(true)
+  }, [])
+
+  return (
+    <View
+      // @ts-expect-error web only
+      onMouseEnter={onMouseEnter}
+      onMouseLeave={onMouseLeave}
+      onFocus={onFocus}
+      onBlur={onMouseLeave}
+      style={StyleSheet.flatten([a.flex_1, a.flex_row])}
+      ref={viewRef}>
+      {isFromSelf && (
+        <View
+          style={[
+            a.mr_xl,
+            a.justify_center,
+            {
+              marginLeft: 'auto',
+            },
+          ]}>
+          <MessageMenu
+            message={message}
+            control={menuControl}
+            triggerOpacity={showActions || menuControl.isOpen ? 1 : 0}
+            onTriggerPress={onMouseEnter}
+            // @ts-expect-error web only
+            onMouseLeave={onMouseLeave}
+          />
+        </View>
+      )}
+      <View
+        style={{
+          maxWidth: '65%',
+        }}>
+        {children}
+      </View>
+      {!isFromSelf && (
+        <View style={[a.flex_row, a.align_center, a.ml_xl]}>
+          <MessageMenu
+            message={message}
+            control={menuControl}
+            triggerOpacity={showActions || menuControl.isOpen ? 1 : 0}
+            onTriggerPress={onMouseEnter}
+            // @ts-expect-error web only
+            onMouseLeave={onMouseLeave}
+          />
+        </View>
+      )}
+    </View>
+  )
+}