about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEric Bailey <git@esb.lol>2024-04-13 00:13:53 -0500
committerGitHub <noreply@github.com>2024-04-13 06:13:53 +0100
commitf5bb348bf51df6f6d35eb23cdf771c184d77fec4 (patch)
treec23990e4f1d3cb1d4dd06433a31423f265fd1ac6
parenta845587e1f0b74b087b0c59d1cdc8e6c5feaf98f (diff)
downloadvoidsky-f5bb348bf51df6f6d35eb23cdf771c184d77fec4.tar.zst
Profile hovers (#3518)
* Add hover card for mentions

* Reposted by

* Fix key

* Add to composer reply to
-rw-r--r--src/components/ProfileHoverCard/index.web.tsx5
-rw-r--r--src/components/ProfileHoverCard/types.ts1
-rw-r--r--src/components/RichText.tsx22
-rw-r--r--src/view/com/composer/ComposerReplyTo.tsx18
-rw-r--r--src/view/com/posts/FeedItem.tsx67
5 files changed, 64 insertions, 49 deletions
diff --git a/src/components/ProfileHoverCard/index.web.tsx b/src/components/ProfileHoverCard/index.web.tsx
index 0d62a52a3..d0e1b58ee 100644
--- a/src/components/ProfileHoverCard/index.web.tsx
+++ b/src/components/ProfileHoverCard/index.web.tsx
@@ -116,7 +116,10 @@ export function ProfileHoverCardInner(props: ProfileHoverCardProps) {
       ref={refs.setReference}
       onPointerEnter={onPointerEnterTarget}
       onPointerLeave={onPointerLeaveTarget}
-      onMouseUp={onClickTarget}>
+      onMouseUp={onClickTarget}
+      style={{
+        display: props.inline ? 'inline' : 'block',
+      }}>
       {props.children}
 
       {hovered && (
diff --git a/src/components/ProfileHoverCard/types.ts b/src/components/ProfileHoverCard/types.ts
index 4e70df5f0..a62279c96 100644
--- a/src/components/ProfileHoverCard/types.ts
+++ b/src/components/ProfileHoverCard/types.ts
@@ -3,4 +3,5 @@ import React from 'react'
 export type ProfileHoverCardProps = {
   children: React.ReactElement
   did: string
+  inline?: boolean
 }
diff --git a/src/components/RichText.tsx b/src/components/RichText.tsx
index 17f36c141..82cdda107 100644
--- a/src/components/RichText.tsx
+++ b/src/components/RichText.tsx
@@ -8,6 +8,7 @@ import {isNative} from '#/platform/detection'
 import {atoms as a, flatten, native, TextStyleProp, useTheme, web} from '#/alf'
 import {useInteractionState} from '#/components/hooks/useInteractionState'
 import {InlineLinkText, LinkProps} from '#/components/Link'
+import {ProfileHoverCard} from '#/components/ProfileHoverCard'
 import {TagMenu, useTagMenuControl} from '#/components/TagMenu'
 import {Text, TextProps} from '#/components/Typography'
 
@@ -86,16 +87,17 @@ export function RichText({
       !disableLinks
     ) {
       els.push(
-        <InlineLinkText
-          selectable={selectable}
-          key={key}
-          to={`/profile/${mention.did}`}
-          style={[...styles, {pointerEvents: 'auto'}]}
-          // @ts-ignore TODO
-          dataSet={WORD_WRAP}
-          onPress={onLinkPress}>
-          {segment.text}
-        </InlineLinkText>,
+        <ProfileHoverCard key={key} inline did={mention.did}>
+          <InlineLinkText
+            selectable={selectable}
+            to={`/profile/${mention.did}`}
+            style={[...styles, {pointerEvents: 'auto'}]}
+            // @ts-ignore TODO
+            dataSet={WORD_WRAP}
+            onPress={onLinkPress}>
+            {segment.text}
+          </InlineLinkText>
+        </ProfileHoverCard>,
       )
     } else if (link && AppBskyRichtextFacet.validateLink(link).success) {
       if (disableLinks) {
diff --git a/src/view/com/composer/ComposerReplyTo.tsx b/src/view/com/composer/ComposerReplyTo.tsx
index 0c1b87d04..24a2373f5 100644
--- a/src/view/com/composer/ComposerReplyTo.tsx
+++ b/src/view/com/composer/ComposerReplyTo.tsx
@@ -1,21 +1,22 @@
 import React from 'react'
 import {LayoutAnimation, Pressable, StyleSheet, View} from 'react-native'
 import {Image} from 'expo-image'
-import {useLingui} from '@lingui/react'
-import {msg} from '@lingui/macro'
 import {
   AppBskyEmbedImages,
   AppBskyEmbedRecord,
   AppBskyEmbedRecordWithMedia,
   AppBskyFeedPost,
 } from '@atproto/api'
-import {ComposerOptsPostRef} from 'state/shell/composer'
+import {msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+
 import {usePalette} from 'lib/hooks/usePalette'
 import {sanitizeDisplayName} from 'lib/strings/display-names'
 import {sanitizeHandle} from 'lib/strings/handles'
-import {UserAvatar} from 'view/com/util/UserAvatar'
-import {Text} from 'view/com/util/text/Text'
+import {ComposerOptsPostRef} from 'state/shell/composer'
 import {QuoteEmbed} from 'view/com/util/post-embeds/QuoteEmbed'
+import {Text} from 'view/com/util/text/Text'
+import {PreviewableUserAvatar} from 'view/com/util/UserAvatar'
 
 export function ComposerReplyTo({replyTo}: {replyTo: ComposerOptsPostRef}) {
   const pal = usePalette('default')
@@ -83,9 +84,11 @@ export function ComposerReplyTo({replyTo}: {replyTo: ComposerOptsPostRef}) {
       accessibilityHint={_(
         msg`Expand or collapse the full post you are replying to`,
       )}>
-      <UserAvatar
-        avatar={replyTo.author.avatar}
+      <PreviewableUserAvatar
         size={50}
+        did={replyTo.author.did}
+        handle={replyTo.author.handle}
+        avatar={replyTo.author.avatar}
         moderation={replyTo.moderation?.ui('avatar')}
         type={replyTo.author.associated?.labeler ? 'labeler' : 'user'}
       />
@@ -216,6 +219,7 @@ function ComposerReplyToImages({
 const styles = StyleSheet.create({
   replyToLayout: {
     flexDirection: 'row',
+    alignItems: 'flex-start',
     borderTopWidth: 1,
     paddingTop: 16,
     paddingBottom: 16,
diff --git a/src/view/com/posts/FeedItem.tsx b/src/view/com/posts/FeedItem.tsx
index 0fbcc4a13..cc403b774 100644
--- a/src/view/com/posts/FeedItem.tsx
+++ b/src/view/com/posts/FeedItem.tsx
@@ -11,31 +11,33 @@ import {
   FontAwesomeIcon,
   FontAwesomeIconStyle,
 } from '@fortawesome/react-native-fontawesome'
-import {ReasonFeedSource, isReasonFeedSource} from 'lib/api/feed/types'
-import {Link, TextLinkOnWebOnly, TextLink} from '../util/Link'
-import {Text} from '../util/text/Text'
-import {UserInfoText} from '../util/UserInfoText'
-import {PostMeta} from '../util/PostMeta'
-import {PostCtrls} from '../util/post-ctrls/PostCtrls'
-import {PostEmbeds} from '../util/post-embeds'
-import {ContentHider} from '#/components/moderation/ContentHider'
-import {PostAlerts} from '../../../components/moderation/PostAlerts'
-import {LabelsOnMyPost} from '../../../components/moderation/LabelsOnMe'
-import {RichText} from '#/components/RichText'
-import {PreviewableUserAvatar} from '../util/UserAvatar'
-import {s} from 'lib/styles'
+import {msg, Trans} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+
+import {POST_TOMBSTONE, Shadow, usePostShadow} from '#/state/cache/post-shadow'
+import {useComposerControls} from '#/state/shell/composer'
+import {isReasonFeedSource, ReasonFeedSource} from 'lib/api/feed/types'
+import {MAX_POST_LINES} from 'lib/constants'
 import {usePalette} from 'lib/hooks/usePalette'
+import {makeProfileLink} from 'lib/routes/links'
 import {sanitizeDisplayName} from 'lib/strings/display-names'
 import {sanitizeHandle} from 'lib/strings/handles'
-import {makeProfileLink} from 'lib/routes/links'
-import {MAX_POST_LINES} from 'lib/constants'
 import {countLines} from 'lib/strings/helpers'
-import {useComposerControls} from '#/state/shell/composer'
-import {Shadow, usePostShadow, POST_TOMBSTONE} from '#/state/cache/post-shadow'
-import {FeedNameText} from '../util/FeedInfoText'
-import {Trans, msg} from '@lingui/macro'
-import {useLingui} from '@lingui/react'
+import {s} from 'lib/styles'
 import {atoms as a} from '#/alf'
+import {ContentHider} from '#/components/moderation/ContentHider'
+import {ProfileHoverCard} from '#/components/ProfileHoverCard'
+import {RichText} from '#/components/RichText'
+import {LabelsOnMyPost} from '../../../components/moderation/LabelsOnMe'
+import {PostAlerts} from '../../../components/moderation/PostAlerts'
+import {FeedNameText} from '../util/FeedInfoText'
+import {Link, TextLink, TextLinkOnWebOnly} from '../util/Link'
+import {PostCtrls} from '../util/post-ctrls/PostCtrls'
+import {PostEmbeds} from '../util/post-embeds'
+import {PostMeta} from '../util/PostMeta'
+import {Text} from '../util/text/Text'
+import {PreviewableUserAvatar} from '../util/UserAvatar'
+import {UserInfoText} from '../util/UserInfoText'
 
 export function FeedItem({
   post,
@@ -213,17 +215,20 @@ let FeedItemInner = ({
                 numberOfLines={1}>
                 <Trans>
                   Reposted by{' '}
-                  <TextLinkOnWebOnly
-                    type="sm-bold"
-                    style={pal.textLight}
-                    lineHeight={1.2}
-                    numberOfLines={1}
-                    text={sanitizeDisplayName(
-                      reason.by.displayName || sanitizeHandle(reason.by.handle),
-                      moderation.ui('displayName'),
-                    )}
-                    href={makeProfileLink(reason.by)}
-                  />
+                  <ProfileHoverCard inline did={reason.by.did}>
+                    <TextLinkOnWebOnly
+                      type="sm-bold"
+                      style={pal.textLight}
+                      lineHeight={1.2}
+                      numberOfLines={1}
+                      text={sanitizeDisplayName(
+                        reason.by.displayName ||
+                          sanitizeHandle(reason.by.handle),
+                        moderation.ui('displayName'),
+                      )}
+                      href={makeProfileLink(reason.by)}
+                    />
+                  </ProfileHoverCard>
                 </Trans>
               </Text>
             </Link>