165 lines
4 KiB
TypeScript
165 lines
4 KiB
TypeScript
import React from 'react'
|
|
import {View} from 'react-native'
|
|
import {
|
|
AppBskyActorDefs,
|
|
AppBskyGraphDefs,
|
|
AtUri,
|
|
moderateUserList,
|
|
ModerationUI,
|
|
} from '@atproto/api'
|
|
import {Trans} from '@lingui/macro'
|
|
import {useQueryClient} from '@tanstack/react-query'
|
|
|
|
import {sanitizeHandle} from 'lib/strings/handles'
|
|
import {useModerationOpts} from 'state/preferences/moderation-opts'
|
|
import {precacheList} from 'state/queries/feed'
|
|
import {useSession} from 'state/session'
|
|
import {atoms as a, useTheme} from '#/alf'
|
|
import {
|
|
Avatar,
|
|
Description,
|
|
Header,
|
|
Outer,
|
|
SaveButton,
|
|
} from '#/components/FeedCard'
|
|
import {Link as InternalLink, LinkProps} from '#/components/Link'
|
|
import * as Hider from '#/components/moderation/Hider'
|
|
import {Text} from '#/components/Typography'
|
|
|
|
/*
|
|
* This component is based on `FeedCard` and is tightly coupled with that
|
|
* component. Please refer to `FeedCard` for more context.
|
|
*/
|
|
|
|
export {
|
|
Avatar,
|
|
AvatarPlaceholder,
|
|
Description,
|
|
Header,
|
|
Outer,
|
|
SaveButton,
|
|
TitleAndBylinePlaceholder,
|
|
} from '#/components/FeedCard'
|
|
|
|
const CURATELIST = 'app.bsky.graph.defs#curatelist'
|
|
const MODLIST = 'app.bsky.graph.defs#modlist'
|
|
|
|
type Props = {
|
|
view: AppBskyGraphDefs.ListView
|
|
showPinButton?: boolean
|
|
}
|
|
|
|
export function Default(props: Props) {
|
|
const {view, showPinButton} = props
|
|
const moderationOpts = useModerationOpts()
|
|
const moderation = moderationOpts
|
|
? moderateUserList(view, moderationOpts)
|
|
: undefined
|
|
|
|
return (
|
|
<Link {...props}>
|
|
<Outer>
|
|
<Header>
|
|
<Avatar src={view.avatar} />
|
|
<TitleAndByline
|
|
title={view.name}
|
|
creator={view.creator}
|
|
purpose={view.purpose}
|
|
modUi={moderation?.ui('contentView')}
|
|
/>
|
|
{showPinButton && view.purpose === CURATELIST && (
|
|
<SaveButton view={view} pin />
|
|
)}
|
|
</Header>
|
|
<Description description={view.description} />
|
|
</Outer>
|
|
</Link>
|
|
)
|
|
}
|
|
|
|
export function Link({
|
|
view,
|
|
children,
|
|
...props
|
|
}: Props & Omit<LinkProps, 'to' | 'label'>) {
|
|
const queryClient = useQueryClient()
|
|
|
|
const href = React.useMemo(() => {
|
|
return createProfileListHref({list: view})
|
|
}, [view])
|
|
|
|
React.useEffect(() => {
|
|
precacheList(queryClient, view)
|
|
}, [view, queryClient])
|
|
|
|
return (
|
|
<InternalLink label={view.name} to={href} {...props}>
|
|
{children}
|
|
</InternalLink>
|
|
)
|
|
}
|
|
|
|
export function TitleAndByline({
|
|
title,
|
|
creator,
|
|
purpose = CURATELIST,
|
|
modUi,
|
|
}: {
|
|
title: string
|
|
creator?: AppBskyActorDefs.ProfileViewBasic
|
|
purpose?: AppBskyGraphDefs.ListView['purpose']
|
|
modUi?: ModerationUI
|
|
}) {
|
|
const t = useTheme()
|
|
const {currentAccount} = useSession()
|
|
|
|
return (
|
|
<View style={[a.flex_1]}>
|
|
<Hider.Outer
|
|
modui={modUi}
|
|
isContentVisibleInitialState={
|
|
creator && currentAccount?.did === creator.did
|
|
}
|
|
allowOverride={creator && currentAccount?.did === creator.did}>
|
|
<Hider.Mask>
|
|
<Text
|
|
style={[a.text_md, a.font_bold, a.leading_snug, a.italic]}
|
|
numberOfLines={1}>
|
|
<Trans>Hidden list</Trans>
|
|
</Text>
|
|
</Hider.Mask>
|
|
<Hider.Content>
|
|
<Text
|
|
style={[a.text_md, a.font_bold, a.leading_snug]}
|
|
numberOfLines={1}>
|
|
{title}
|
|
</Text>
|
|
</Hider.Content>
|
|
</Hider.Outer>
|
|
|
|
{creator && (
|
|
<Text
|
|
style={[a.leading_snug, t.atoms.text_contrast_medium]}
|
|
numberOfLines={1}>
|
|
{purpose === MODLIST ? (
|
|
<Trans>
|
|
Moderation list by {sanitizeHandle(creator.handle, '@')}
|
|
</Trans>
|
|
) : (
|
|
<Trans>List by {sanitizeHandle(creator.handle, '@')}</Trans>
|
|
)}
|
|
</Text>
|
|
)}
|
|
</View>
|
|
)
|
|
}
|
|
|
|
export function createProfileListHref({
|
|
list,
|
|
}: {
|
|
list: AppBskyGraphDefs.ListView
|
|
}) {
|
|
const urip = new AtUri(list.uri)
|
|
const handleOrDid = list.creator.handle || list.creator.did
|
|
return `/profile/${handleOrDid}/lists/${urip.rkey}`
|
|
}
|