about summary refs log tree commit diff
path: root/src/components/PostControls/ShareMenu/ShareMenuItems.tsx
diff options
context:
space:
mode:
authorSamuel Newman <mozzius@protonmail.com>2025-05-24 02:02:38 +0300
committerGitHub <noreply@github.com>2025-05-23 18:02:38 -0500
commitc3f88e0a48bdf22831736ad3d44222e7c4418486 (patch)
treed72137786908d5c61ad52a7cb7aa8fd37472a615 /src/components/PostControls/ShareMenu/ShareMenuItems.tsx
parent5aadb9e41b1305e673947b28ba0566bdc3a3325d (diff)
downloadvoidsky-c3f88e0a48bdf22831736ad3d44222e7c4418486.tar.zst
Share menu (#7840)
* move post ctrls to #/components

* restructure post controls, basic share menu

* add border radius to searchable people list for android

* Revert "add border radius to searchable people list for android"

This reverts commit 417449086e25b82f5683b12f6405d972f48ce50e.

* add copy link to native share menu

* reorg files again

* open native share menu on long press

* Translation comments

Thanks @surfdude29

* abs path

* update type imports, remove forwardRef

* rm react import

* equal spacing of buttons, extract disco debug

* add better icon

* add right offset to share button for visual alignment

* Add recent chats to share menu (#7853)

* add recent chats to share menu

* Update RecentChats.tsx

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>

* Update RecentChats.tsx

* add fading edge on andriod

* tweak scrollview

* Add metrics and A/B alt icon to share menu (#8401)

* add metrics

* add a/b tested alt icon

---------

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>

* More descriptive share text/icon on web (#7854)

* more descriptive share text on web

* revert dev mode changes

* add missing import

* use modified share icon everywhere

* Add back conflicting changes

---------

Co-authored-by: Eric Bailey <git@esb.lol>

---------

Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com>
Co-authored-by: Eric Bailey <git@esb.lol>
Diffstat (limited to 'src/components/PostControls/ShareMenu/ShareMenuItems.tsx')
-rw-r--r--src/components/PostControls/ShareMenu/ShareMenuItems.tsx197
1 files changed, 197 insertions, 0 deletions
diff --git a/src/components/PostControls/ShareMenu/ShareMenuItems.tsx b/src/components/PostControls/ShareMenu/ShareMenuItems.tsx
new file mode 100644
index 000000000..94369fcff
--- /dev/null
+++ b/src/components/PostControls/ShareMenu/ShareMenuItems.tsx
@@ -0,0 +1,197 @@
+import {memo, useMemo} from 'react'
+import * as ExpoClipboard from 'expo-clipboard'
+import {AtUri} from '@atproto/api'
+import {msg, Trans} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+import {useNavigation} from '@react-navigation/native'
+
+import {makeProfileLink} from '#/lib/routes/links'
+import {type NavigationProp} from '#/lib/routes/types'
+import {shareText, shareUrl} from '#/lib/sharing'
+import {toShareUrl} from '#/lib/strings/url-helpers'
+import {logger} from '#/logger'
+import {useProfileShadow} from '#/state/cache/profile-shadow'
+import {useSession} from '#/state/session'
+import * as Toast from '#/view/com/util/Toast'
+import {useDialogControl} from '#/components/Dialog'
+import {SendViaChatDialog} from '#/components/dms/dialogs/ShareViaChatDialog'
+import {ArrowOutOfBoxModified_Stroke2_Corner2_Rounded as ArrowOutOfBoxIcon} from '#/components/icons/ArrowOutOfBox'
+import {ChainLink_Stroke2_Corner0_Rounded as ChainLinkIcon} from '#/components/icons/ChainLink'
+import {Clipboard_Stroke2_Corner2_Rounded as ClipboardIcon} from '#/components/icons/Clipboard'
+import {PaperPlane_Stroke2_Corner0_Rounded as PaperPlaneIcon} from '#/components/icons/PaperPlane'
+import * as Menu from '#/components/Menu'
+import * as Prompt from '#/components/Prompt'
+import {useDevMode} from '#/storage/hooks/dev-mode'
+import {RecentChats} from './RecentChats'
+import {type ShareMenuItemsProps} from './ShareMenuItems.types'
+
+let ShareMenuItems = ({
+  post,
+  onShare: onShareProp,
+}: ShareMenuItemsProps): React.ReactNode => {
+  const {hasSession, currentAccount} = useSession()
+  const {_} = useLingui()
+  const navigation = useNavigation<NavigationProp>()
+  const pwiWarningShareControl = useDialogControl()
+  const pwiWarningCopyControl = useDialogControl()
+  const sendViaChatControl = useDialogControl()
+  const [devModeEnabled] = useDevMode()
+
+  const postUri = post.uri
+  const postAuthor = useProfileShadow(post.author)
+
+  const href = useMemo(() => {
+    const urip = new AtUri(postUri)
+    return makeProfileLink(postAuthor, 'post', urip.rkey)
+  }, [postUri, postAuthor])
+
+  const hideInPWI = useMemo(() => {
+    return !!postAuthor.labels?.find(
+      label => label.val === '!no-unauthenticated',
+    )
+  }, [postAuthor])
+
+  const showLoggedOutWarning =
+    postAuthor.did !== currentAccount?.did && hideInPWI
+
+  const onSharePost = () => {
+    logger.metric('share:press:nativeShare', {}, {statsig: true})
+    const url = toShareUrl(href)
+    shareUrl(url)
+    onShareProp()
+  }
+
+  const onCopyLink = () => {
+    logger.metric('share:press:copyLink', {}, {statsig: true})
+    const url = toShareUrl(href)
+    ExpoClipboard.setUrlAsync(url).then(() =>
+      Toast.show(_(msg`Copied to clipboard`), 'clipboard-check'),
+    )
+    onShareProp()
+  }
+
+  const onSelectChatToShareTo = (conversation: string) => {
+    navigation.navigate('MessagesConversation', {
+      conversation,
+      embed: postUri,
+    })
+  }
+
+  const onShareATURI = () => {
+    shareText(postUri)
+  }
+
+  const onShareAuthorDID = () => {
+    shareText(postAuthor.did)
+  }
+
+  return (
+    <>
+      <Menu.Outer>
+        {hasSession && (
+          <Menu.Group>
+            <Menu.ContainerItem>
+              <RecentChats postUri={postUri} />
+            </Menu.ContainerItem>
+            <Menu.Item
+              testID="postDropdownSendViaDMBtn"
+              label={_(msg`Send via direct message`)}
+              onPress={() => {
+                logger.metric('share:press:openDmSearch', {}, {statsig: true})
+                sendViaChatControl.open()
+              }}>
+              <Menu.ItemText>
+                <Trans>Send via direct message</Trans>
+              </Menu.ItemText>
+              <Menu.ItemIcon icon={PaperPlaneIcon} position="right" />
+            </Menu.Item>
+          </Menu.Group>
+        )}
+
+        <Menu.Group>
+          <Menu.Item
+            testID="postDropdownShareBtn"
+            label={_(msg`Share via...`)}
+            onPress={() => {
+              if (showLoggedOutWarning) {
+                pwiWarningShareControl.open()
+              } else {
+                onSharePost()
+              }
+            }}>
+            <Menu.ItemText>
+              <Trans>Share via...</Trans>
+            </Menu.ItemText>
+            <Menu.ItemIcon icon={ArrowOutOfBoxIcon} position="right" />
+          </Menu.Item>
+
+          <Menu.Item
+            testID="postDropdownShareBtn"
+            label={_(msg`Copy link to post`)}
+            onPress={() => {
+              if (showLoggedOutWarning) {
+                pwiWarningCopyControl.open()
+              } else {
+                onCopyLink()
+              }
+            }}>
+            <Menu.ItemText>
+              <Trans>Copy link to post</Trans>
+            </Menu.ItemText>
+            <Menu.ItemIcon icon={ChainLinkIcon} position="right" />
+          </Menu.Item>
+        </Menu.Group>
+
+        {devModeEnabled && (
+          <Menu.Group>
+            <Menu.Item
+              testID="postAtUriShareBtn"
+              label={_(msg`Share post at:// URI`)}
+              onPress={onShareATURI}>
+              <Menu.ItemText>
+                <Trans>Share post at:// URI</Trans>
+              </Menu.ItemText>
+              <Menu.ItemIcon icon={ClipboardIcon} position="right" />
+            </Menu.Item>
+            <Menu.Item
+              testID="postAuthorDIDShareBtn"
+              label={_(msg`Share author DID`)}
+              onPress={onShareAuthorDID}>
+              <Menu.ItemText>
+                <Trans>Share author DID</Trans>
+              </Menu.ItemText>
+              <Menu.ItemIcon icon={ClipboardIcon} position="right" />
+            </Menu.Item>
+          </Menu.Group>
+        )}
+      </Menu.Outer>
+
+      <Prompt.Basic
+        control={pwiWarningShareControl}
+        title={_(msg`Note about sharing`)}
+        description={_(
+          msg`This post is only visible to logged-in users. It won't be visible to people who aren't signed in.`,
+        )}
+        onConfirm={onSharePost}
+        confirmButtonCta={_(msg`Share anyway`)}
+      />
+
+      <Prompt.Basic
+        control={pwiWarningCopyControl}
+        title={_(msg`Note about sharing`)}
+        description={_(
+          msg`This post is only visible to logged-in users. It won't be visible to people who aren't signed in.`,
+        )}
+        onConfirm={onCopyLink}
+        confirmButtonCta={_(msg`Copy anyway`)}
+      />
+
+      <SendViaChatDialog
+        control={sendViaChatControl}
+        onSelectChat={onSelectChatToShareTo}
+      />
+    </>
+  )
+}
+ShareMenuItems = memo(ShareMenuItems)
+export {ShareMenuItems}