Profile hovers (#3518)
* Add hover card for mentions * Reposted by * Fix key * Add to composer reply tozio/stable
parent
a845587e1f
commit
f5bb348bf5
|
@ -116,7 +116,10 @@ export function ProfileHoverCardInner(props: ProfileHoverCardProps) {
|
||||||
ref={refs.setReference}
|
ref={refs.setReference}
|
||||||
onPointerEnter={onPointerEnterTarget}
|
onPointerEnter={onPointerEnterTarget}
|
||||||
onPointerLeave={onPointerLeaveTarget}
|
onPointerLeave={onPointerLeaveTarget}
|
||||||
onMouseUp={onClickTarget}>
|
onMouseUp={onClickTarget}
|
||||||
|
style={{
|
||||||
|
display: props.inline ? 'inline' : 'block',
|
||||||
|
}}>
|
||||||
{props.children}
|
{props.children}
|
||||||
|
|
||||||
{hovered && (
|
{hovered && (
|
||||||
|
|
|
@ -3,4 +3,5 @@ import React from 'react'
|
||||||
export type ProfileHoverCardProps = {
|
export type ProfileHoverCardProps = {
|
||||||
children: React.ReactElement
|
children: React.ReactElement
|
||||||
did: string
|
did: string
|
||||||
|
inline?: boolean
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {isNative} from '#/platform/detection'
|
||||||
import {atoms as a, flatten, native, TextStyleProp, useTheme, web} from '#/alf'
|
import {atoms as a, flatten, native, TextStyleProp, useTheme, web} from '#/alf'
|
||||||
import {useInteractionState} from '#/components/hooks/useInteractionState'
|
import {useInteractionState} from '#/components/hooks/useInteractionState'
|
||||||
import {InlineLinkText, LinkProps} from '#/components/Link'
|
import {InlineLinkText, LinkProps} from '#/components/Link'
|
||||||
|
import {ProfileHoverCard} from '#/components/ProfileHoverCard'
|
||||||
import {TagMenu, useTagMenuControl} from '#/components/TagMenu'
|
import {TagMenu, useTagMenuControl} from '#/components/TagMenu'
|
||||||
import {Text, TextProps} from '#/components/Typography'
|
import {Text, TextProps} from '#/components/Typography'
|
||||||
|
|
||||||
|
@ -86,16 +87,17 @@ export function RichText({
|
||||||
!disableLinks
|
!disableLinks
|
||||||
) {
|
) {
|
||||||
els.push(
|
els.push(
|
||||||
|
<ProfileHoverCard key={key} inline did={mention.did}>
|
||||||
<InlineLinkText
|
<InlineLinkText
|
||||||
selectable={selectable}
|
selectable={selectable}
|
||||||
key={key}
|
|
||||||
to={`/profile/${mention.did}`}
|
to={`/profile/${mention.did}`}
|
||||||
style={[...styles, {pointerEvents: 'auto'}]}
|
style={[...styles, {pointerEvents: 'auto'}]}
|
||||||
// @ts-ignore TODO
|
// @ts-ignore TODO
|
||||||
dataSet={WORD_WRAP}
|
dataSet={WORD_WRAP}
|
||||||
onPress={onLinkPress}>
|
onPress={onLinkPress}>
|
||||||
{segment.text}
|
{segment.text}
|
||||||
</InlineLinkText>,
|
</InlineLinkText>
|
||||||
|
</ProfileHoverCard>,
|
||||||
)
|
)
|
||||||
} else if (link && AppBskyRichtextFacet.validateLink(link).success) {
|
} else if (link && AppBskyRichtextFacet.validateLink(link).success) {
|
||||||
if (disableLinks) {
|
if (disableLinks) {
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {LayoutAnimation, Pressable, StyleSheet, View} from 'react-native'
|
import {LayoutAnimation, Pressable, StyleSheet, View} from 'react-native'
|
||||||
import {Image} from 'expo-image'
|
import {Image} from 'expo-image'
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
import {msg} from '@lingui/macro'
|
|
||||||
import {
|
import {
|
||||||
AppBskyEmbedImages,
|
AppBskyEmbedImages,
|
||||||
AppBskyEmbedRecord,
|
AppBskyEmbedRecord,
|
||||||
AppBskyEmbedRecordWithMedia,
|
AppBskyEmbedRecordWithMedia,
|
||||||
AppBskyFeedPost,
|
AppBskyFeedPost,
|
||||||
} from '@atproto/api'
|
} 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 {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {sanitizeDisplayName} from 'lib/strings/display-names'
|
import {sanitizeDisplayName} from 'lib/strings/display-names'
|
||||||
import {sanitizeHandle} from 'lib/strings/handles'
|
import {sanitizeHandle} from 'lib/strings/handles'
|
||||||
import {UserAvatar} from 'view/com/util/UserAvatar'
|
import {ComposerOptsPostRef} from 'state/shell/composer'
|
||||||
import {Text} from 'view/com/util/text/Text'
|
|
||||||
import {QuoteEmbed} from 'view/com/util/post-embeds/QuoteEmbed'
|
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}) {
|
export function ComposerReplyTo({replyTo}: {replyTo: ComposerOptsPostRef}) {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
@ -83,9 +84,11 @@ export function ComposerReplyTo({replyTo}: {replyTo: ComposerOptsPostRef}) {
|
||||||
accessibilityHint={_(
|
accessibilityHint={_(
|
||||||
msg`Expand or collapse the full post you are replying to`,
|
msg`Expand or collapse the full post you are replying to`,
|
||||||
)}>
|
)}>
|
||||||
<UserAvatar
|
<PreviewableUserAvatar
|
||||||
avatar={replyTo.author.avatar}
|
|
||||||
size={50}
|
size={50}
|
||||||
|
did={replyTo.author.did}
|
||||||
|
handle={replyTo.author.handle}
|
||||||
|
avatar={replyTo.author.avatar}
|
||||||
moderation={replyTo.moderation?.ui('avatar')}
|
moderation={replyTo.moderation?.ui('avatar')}
|
||||||
type={replyTo.author.associated?.labeler ? 'labeler' : 'user'}
|
type={replyTo.author.associated?.labeler ? 'labeler' : 'user'}
|
||||||
/>
|
/>
|
||||||
|
@ -216,6 +219,7 @@ function ComposerReplyToImages({
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
replyToLayout: {
|
replyToLayout: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
|
alignItems: 'flex-start',
|
||||||
borderTopWidth: 1,
|
borderTopWidth: 1,
|
||||||
paddingTop: 16,
|
paddingTop: 16,
|
||||||
paddingBottom: 16,
|
paddingBottom: 16,
|
||||||
|
|
|
@ -11,31 +11,33 @@ import {
|
||||||
FontAwesomeIcon,
|
FontAwesomeIcon,
|
||||||
FontAwesomeIconStyle,
|
FontAwesomeIconStyle,
|
||||||
} from '@fortawesome/react-native-fontawesome'
|
} from '@fortawesome/react-native-fontawesome'
|
||||||
import {ReasonFeedSource, isReasonFeedSource} from 'lib/api/feed/types'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
import {Link, TextLinkOnWebOnly, TextLink} from '../util/Link'
|
import {useLingui} from '@lingui/react'
|
||||||
import {Text} from '../util/text/Text'
|
|
||||||
import {UserInfoText} from '../util/UserInfoText'
|
import {POST_TOMBSTONE, Shadow, usePostShadow} from '#/state/cache/post-shadow'
|
||||||
import {PostMeta} from '../util/PostMeta'
|
import {useComposerControls} from '#/state/shell/composer'
|
||||||
import {PostCtrls} from '../util/post-ctrls/PostCtrls'
|
import {isReasonFeedSource, ReasonFeedSource} from 'lib/api/feed/types'
|
||||||
import {PostEmbeds} from '../util/post-embeds'
|
import {MAX_POST_LINES} from 'lib/constants'
|
||||||
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 {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
import {makeProfileLink} from 'lib/routes/links'
|
||||||
import {sanitizeDisplayName} from 'lib/strings/display-names'
|
import {sanitizeDisplayName} from 'lib/strings/display-names'
|
||||||
import {sanitizeHandle} from 'lib/strings/handles'
|
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 {countLines} from 'lib/strings/helpers'
|
||||||
import {useComposerControls} from '#/state/shell/composer'
|
import {s} from 'lib/styles'
|
||||||
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 {atoms as a} from '#/alf'
|
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({
|
export function FeedItem({
|
||||||
post,
|
post,
|
||||||
|
@ -213,17 +215,20 @@ let FeedItemInner = ({
|
||||||
numberOfLines={1}>
|
numberOfLines={1}>
|
||||||
<Trans>
|
<Trans>
|
||||||
Reposted by{' '}
|
Reposted by{' '}
|
||||||
|
<ProfileHoverCard inline did={reason.by.did}>
|
||||||
<TextLinkOnWebOnly
|
<TextLinkOnWebOnly
|
||||||
type="sm-bold"
|
type="sm-bold"
|
||||||
style={pal.textLight}
|
style={pal.textLight}
|
||||||
lineHeight={1.2}
|
lineHeight={1.2}
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
text={sanitizeDisplayName(
|
text={sanitizeDisplayName(
|
||||||
reason.by.displayName || sanitizeHandle(reason.by.handle),
|
reason.by.displayName ||
|
||||||
|
sanitizeHandle(reason.by.handle),
|
||||||
moderation.ui('displayName'),
|
moderation.ui('displayName'),
|
||||||
)}
|
)}
|
||||||
href={makeProfileLink(reason.by)}
|
href={makeProfileLink(reason.by)}
|
||||||
/>
|
/>
|
||||||
|
</ProfileHoverCard>
|
||||||
</Trans>
|
</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
Loading…
Reference in New Issue