Let specified facets take priority in feed descriptions (#10740)
This commit is contained in:
@@ -1346,9 +1346,6 @@
|
||||
}
|
||||
},
|
||||
"src/screens/Profile/components/ProfileFeedHeader.tsx": {
|
||||
"@typescript-eslint/no-floating-promises": {
|
||||
"count": 1
|
||||
},
|
||||
"@typescript-eslint/no-misused-promises": {
|
||||
"count": 5
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import {useCallback, useMemo, useState} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {AtUri} from '@atproto/api'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {Plural, Trans} from '@lingui/react/macro'
|
||||
import {Plural, Trans, useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {useHaptics} from '#/lib/haptics'
|
||||
import {makeCustomFeedLink, makeProfileLink} from '#/lib/routes/links'
|
||||
@@ -26,7 +24,6 @@ import {atoms as a, useBreakpoints, useTheme, web} from '#/alf'
|
||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
import {Divider} from '#/components/Divider'
|
||||
import {useRichText} from '#/components/hooks/useRichText'
|
||||
import {ArrowOutOfBoxModified_Stroke2_Corner2_Rounded as Share} from '#/components/icons/ArrowOutOfBox'
|
||||
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
|
||||
import {DotGrid3x1_Stroke2_Corner0_Rounded as Ellipsis} from '#/components/icons/DotGrid'
|
||||
@@ -86,7 +83,7 @@ export function ProfileFeedHeaderSkeleton() {
|
||||
|
||||
export function ProfileFeedHeader({info}: {info: FeedSourceFeedInfo}) {
|
||||
const t = useTheme()
|
||||
const {_, i18n} = useLingui()
|
||||
const {t: l, i18n} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const {hasSession} = useSession()
|
||||
const {gtMobile} = useBreakpoints()
|
||||
@@ -121,7 +118,7 @@ export function ProfileFeedHeader({info}: {info: FeedSourceFeedInfo}) {
|
||||
|
||||
if (savedFeedConfig) {
|
||||
await removeFeed(savedFeedConfig)
|
||||
Toast.show(_(msg`Removed from your feeds`))
|
||||
Toast.show(l`Removed from your feeds`)
|
||||
ax.metric('feed:unsave', {feedUrl: info.uri})
|
||||
} else {
|
||||
await addSavedFeeds([
|
||||
@@ -131,14 +128,12 @@ export function ProfileFeedHeader({info}: {info: FeedSourceFeedInfo}) {
|
||||
pinned: false,
|
||||
},
|
||||
])
|
||||
Toast.show(_(msg`Saved to your feeds`))
|
||||
Toast.show(l`Saved to your feeds`)
|
||||
ax.metric('feed:save', {feedUrl: info.uri})
|
||||
}
|
||||
} catch (err) {
|
||||
Toast.show(
|
||||
_(
|
||||
msg`There was an issue updating your feeds, please check your internet connection and try again.`,
|
||||
),
|
||||
l`There was an issue updating your feeds, please check your internet connection and try again.`,
|
||||
{
|
||||
type: 'error',
|
||||
},
|
||||
@@ -161,10 +156,10 @@ export function ProfileFeedHeader({info}: {info: FeedSourceFeedInfo}) {
|
||||
])
|
||||
|
||||
if (pinned) {
|
||||
Toast.show(_(msg`Pinned ${info.displayName} to Home`))
|
||||
Toast.show(l`Pinned ${info.displayName} to Home`)
|
||||
ax.metric('feed:pin', {feedUrl: info.uri})
|
||||
} else {
|
||||
Toast.show(_(msg`Unpinned ${info.displayName} from Home`))
|
||||
Toast.show(l`Unpinned ${info.displayName} from Home`)
|
||||
ax.metric('feed:unpin', {feedUrl: info.uri})
|
||||
}
|
||||
} else {
|
||||
@@ -175,11 +170,11 @@ export function ProfileFeedHeader({info}: {info: FeedSourceFeedInfo}) {
|
||||
pinned: true,
|
||||
},
|
||||
])
|
||||
Toast.show(_(msg`Pinned ${info.displayName} to Home`))
|
||||
Toast.show(l`Pinned ${info.displayName} to Home`)
|
||||
ax.metric('feed:pin', {feedUrl: info.uri})
|
||||
}
|
||||
} catch (e) {
|
||||
Toast.show(_(msg`There was an issue contacting the server`), {
|
||||
Toast.show(l`There was an issue contacting the server`, {
|
||||
type: 'error',
|
||||
})
|
||||
logger.error('Failed to toggle pinned feed', {message: e})
|
||||
@@ -194,7 +189,7 @@ export function ProfileFeedHeader({info}: {info: FeedSourceFeedInfo}) {
|
||||
<Layout.Header.BackButton />
|
||||
<Layout.Header.Content align="left">
|
||||
<Button
|
||||
label={_(msg`Open feed info screen`)}
|
||||
label={l`Open feed info screen`}
|
||||
style={[
|
||||
a.justify_start,
|
||||
{
|
||||
@@ -295,12 +290,12 @@ export function ProfileFeedHeader({info}: {info: FeedSourceFeedInfo}) {
|
||||
<Layout.Header.Slot>
|
||||
{isPinned ? (
|
||||
<Menu.Root>
|
||||
<Menu.Trigger label={_(msg`Open feed options menu`)}>
|
||||
<Menu.Trigger label={l`Open feed options menu`}>
|
||||
{({props}) => {
|
||||
return (
|
||||
<Button
|
||||
{...props}
|
||||
label={_(msg`Open feed options menu`)}
|
||||
label={l`Open feed options menu`}
|
||||
size="small"
|
||||
variant="ghost"
|
||||
shape="square"
|
||||
@@ -314,23 +309,21 @@ export function ProfileFeedHeader({info}: {info: FeedSourceFeedInfo}) {
|
||||
<Menu.Outer>
|
||||
<Menu.Item
|
||||
disabled={isFeedStateChangePending}
|
||||
label={_(msg`Unpin from home`)}
|
||||
label={l`Unpin from home`}
|
||||
onPress={onTogglePinned}>
|
||||
<Menu.ItemText>{_(msg`Unpin from home`)}</Menu.ItemText>
|
||||
<Menu.ItemText>{l`Unpin from home`}</Menu.ItemText>
|
||||
<Menu.ItemIcon icon={X} position="right" />
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
disabled={isFeedStateChangePending}
|
||||
label={
|
||||
isSaved
|
||||
? _(msg`Remove from my feeds`)
|
||||
: _(msg`Save to my feeds`)
|
||||
isSaved ? l`Remove from my feeds` : l`Save to my feeds`
|
||||
}
|
||||
onPress={onToggleSaved}>
|
||||
<Menu.ItemText>
|
||||
{isSaved
|
||||
? _(msg`Remove from my feeds`)
|
||||
: _(msg`Save to my feeds`)}
|
||||
? l`Remove from my feeds`
|
||||
: l`Save to my feeds`}
|
||||
</Menu.ItemText>
|
||||
<Menu.ItemIcon
|
||||
icon={isSaved ? Trash : Plus}
|
||||
@@ -341,7 +334,7 @@ export function ProfileFeedHeader({info}: {info: FeedSourceFeedInfo}) {
|
||||
</Menu.Root>
|
||||
) : (
|
||||
<Button
|
||||
label={_(msg`Pin to Home`)}
|
||||
label={l`Pin to Home`}
|
||||
size="small"
|
||||
variant="ghost"
|
||||
shape="square"
|
||||
@@ -354,11 +347,10 @@ export function ProfileFeedHeader({info}: {info: FeedSourceFeedInfo}) {
|
||||
)}
|
||||
</Layout.Header.Outer>
|
||||
</Layout.Center>
|
||||
|
||||
<Dialog.Outer control={infoControl}>
|
||||
<Dialog.Handle />
|
||||
<Dialog.ScrollableInner
|
||||
label={_(msg`Feed menu`)}
|
||||
label={l`Feed menu`}
|
||||
style={[gtMobile ? {width: 'auto', minWidth: 450} : a.w_full]}>
|
||||
<DialogInner
|
||||
info={info}
|
||||
@@ -393,13 +385,12 @@ function DialogInner({
|
||||
isFeedStateChangePending: boolean
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const {t: l} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
const {hasSession} = useSession()
|
||||
const playHaptic = useHaptics()
|
||||
const control = Dialog.useDialogContext()
|
||||
const reportDialogControl = useReportDialogControl()
|
||||
const [rt] = useRichText(info.description.text)
|
||||
const {mutateAsync: likeFeed, isPending: isLikePending} = useLikeMutation()
|
||||
const {mutateAsync: unlikeFeed, isPending: isUnlikePending} =
|
||||
useUnlikeMutation()
|
||||
@@ -422,9 +413,7 @@ function DialogInner({
|
||||
}
|
||||
} catch (err) {
|
||||
Toast.show(
|
||||
_(
|
||||
msg`There was an issue contacting the server, please check your internet connection and try again.`,
|
||||
),
|
||||
l`There was an issue contacting the server, please check your internet connection and try again.`,
|
||||
{
|
||||
type: 'error',
|
||||
},
|
||||
@@ -436,9 +425,9 @@ function DialogInner({
|
||||
const onPressShare = useCallback(() => {
|
||||
playHaptic()
|
||||
const url = toShareUrl(info.route.href)
|
||||
shareUrl(url)
|
||||
void shareUrl(url)
|
||||
ax.metric('feed:share', {feedUrl: info.uri})
|
||||
}, [info, playHaptic])
|
||||
}, [ax, info, playHaptic])
|
||||
|
||||
const onPressReport = useCallback(() => {
|
||||
reportDialogControl.open()
|
||||
@@ -462,7 +451,7 @@ function DialogInner({
|
||||
<Trans>
|
||||
By{' '}
|
||||
<InlineLinkText
|
||||
label={_(msg`View ${info.creatorHandle}'s profile`)}
|
||||
label={l`View ${info.creatorHandle}'s profile`}
|
||||
to={makeProfileLink({
|
||||
did: info.creatorDid,
|
||||
handle: info.creatorHandle,
|
||||
@@ -477,7 +466,7 @@ function DialogInner({
|
||||
</View>
|
||||
|
||||
<Button
|
||||
label={_(msg`Share this feed`)}
|
||||
label={l`Share this feed`}
|
||||
size="small"
|
||||
variant="ghost"
|
||||
color="secondary"
|
||||
@@ -486,13 +475,11 @@ function DialogInner({
|
||||
<ButtonIcon icon={Share} size="lg" />
|
||||
</Button>
|
||||
</View>
|
||||
|
||||
<RichText value={rt} style={[a.text_md]} />
|
||||
|
||||
<RichText value={info.description} style={[a.text_md]} />
|
||||
<View style={[a.flex_row, a.gap_sm, a.align_center]}>
|
||||
{typeof likeCount === 'number' && (
|
||||
<InlineLinkText
|
||||
label={_(msg`View users who like this feed`)}
|
||||
label={l`View users who like this feed`}
|
||||
to={makeCustomFeedLink(info.creatorDid, feedRkey, 'liked-by')}
|
||||
style={[a.underline, t.atoms.text_contrast_medium]}
|
||||
onPress={() => control.close()}>
|
||||
@@ -502,13 +489,12 @@ function DialogInner({
|
||||
</InlineLinkText>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{hasSession && (
|
||||
<>
|
||||
<View style={[a.flex_row, a.gap_sm, a.align_center, a.pt_sm]}>
|
||||
<Button
|
||||
disabled={isLikePending || isUnlikePending}
|
||||
label={_(msg`Like this feed`)}
|
||||
label={l`Like this feed`}
|
||||
size="small"
|
||||
color="secondary"
|
||||
onPress={onToggleLiked}
|
||||
@@ -525,7 +511,7 @@ function DialogInner({
|
||||
</Button>
|
||||
<Button
|
||||
disabled={isFeedStateChangePending}
|
||||
label={isPinned ? _(msg`Unpin feed`) : _(msg`Pin feed`)}
|
||||
label={isPinned ? l`Unpin feed` : l`Pin feed`}
|
||||
size="small"
|
||||
color={isPinned ? 'secondary' : 'primary'}
|
||||
onPress={onTogglePinned}
|
||||
@@ -547,7 +533,7 @@ function DialogInner({
|
||||
</Text>
|
||||
|
||||
<Button
|
||||
label={_(msg`Report feed`)}
|
||||
label={l`Report feed`}
|
||||
size="small"
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
|
||||
@@ -101,6 +101,15 @@ export function hydrateFeedGenerator(
|
||||
const href = `/profile/${urip.hostname}/${collection}/${urip.rkey}`
|
||||
const route = router.matchPath(href)
|
||||
|
||||
const description = new RichText({
|
||||
text: view.description || '',
|
||||
facets: (view.descriptionFacets || [])?.slice(),
|
||||
})
|
||||
|
||||
if (!view.descriptionFacets) {
|
||||
description.detectFacetsWithoutResolution()
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'feed',
|
||||
view,
|
||||
@@ -116,10 +125,7 @@ export function hydrateFeedGenerator(
|
||||
displayName: view.displayName
|
||||
? sanitizeDisplayName(view.displayName)
|
||||
: t`Feed by ${sanitizeHandle(view.creator.handle, '@')}`,
|
||||
description: new RichText({
|
||||
text: view.description || '',
|
||||
facets: (view.descriptionFacets || [])?.slice(),
|
||||
}),
|
||||
description,
|
||||
creatorDid: view.creator.did,
|
||||
creatorHandle: view.creator.handle,
|
||||
likeCount: view.likeCount,
|
||||
@@ -136,6 +142,15 @@ export function hydrateList(view: AppBskyGraphDefs.ListView): FeedSourceInfo {
|
||||
const href = `/profile/${urip.hostname}/${collection}/${urip.rkey}`
|
||||
const route = router.matchPath(href)
|
||||
|
||||
const description = new RichText({
|
||||
text: view.description || '',
|
||||
facets: (view.descriptionFacets || [])?.slice(),
|
||||
})
|
||||
|
||||
if (!view.descriptionFacets) {
|
||||
description.detectFacetsWithoutResolution()
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'list',
|
||||
view,
|
||||
@@ -148,10 +163,7 @@ export function hydrateList(view: AppBskyGraphDefs.ListView): FeedSourceInfo {
|
||||
},
|
||||
cid: view.cid,
|
||||
avatar: view.avatar,
|
||||
description: new RichText({
|
||||
text: view.description || '',
|
||||
facets: (view.descriptionFacets || [])?.slice(),
|
||||
}),
|
||||
description,
|
||||
creatorDid: view.creator.did,
|
||||
creatorHandle: view.creator.handle,
|
||||
displayName: view.name
|
||||
|
||||
Reference in New Issue
Block a user