mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
at samuel/exp-cli 165 lines 4.1 kB view raw
1import React from 'react' 2import {View} from 'react-native' 3import { 4 AppBskyGraphDefs, 5 AtUri, 6 moderateUserList, 7 ModerationUI, 8} from '@atproto/api' 9import {msg, Trans} from '@lingui/macro' 10import {useLingui} from '@lingui/react' 11import {useQueryClient} from '@tanstack/react-query' 12 13import {sanitizeHandle} from '#/lib/strings/handles' 14import {useModerationOpts} from '#/state/preferences/moderation-opts' 15import {precacheList} from '#/state/queries/feed' 16import {useSession} from '#/state/session' 17import {atoms as a, useTheme} from '#/alf' 18import { 19 Avatar, 20 Description, 21 Header, 22 Outer, 23 SaveButton, 24} from '#/components/FeedCard' 25import {Link as InternalLink, LinkProps} from '#/components/Link' 26import * as Hider from '#/components/moderation/Hider' 27import {Text} from '#/components/Typography' 28import * as bsky from '#/types/bsky' 29 30/* 31 * This component is based on `FeedCard` and is tightly coupled with that 32 * component. Please refer to `FeedCard` for more context. 33 */ 34 35export { 36 Avatar, 37 AvatarPlaceholder, 38 Description, 39 Header, 40 Outer, 41 SaveButton, 42 TitleAndBylinePlaceholder, 43} from '#/components/FeedCard' 44 45const CURATELIST = 'app.bsky.graph.defs#curatelist' 46const MODLIST = 'app.bsky.graph.defs#modlist' 47 48type Props = { 49 view: AppBskyGraphDefs.ListView 50 showPinButton?: boolean 51} 52 53export function Default(props: Props) { 54 const {view, showPinButton} = props 55 const moderationOpts = useModerationOpts() 56 const moderation = moderationOpts 57 ? moderateUserList(view, moderationOpts) 58 : undefined 59 60 return ( 61 <Link {...props}> 62 <Outer> 63 <Header> 64 <Avatar src={view.avatar} /> 65 <TitleAndByline 66 title={view.name} 67 creator={view.creator} 68 purpose={view.purpose} 69 modUi={moderation?.ui('contentView')} 70 /> 71 {showPinButton && view.purpose === CURATELIST && ( 72 <SaveButton view={view} pin /> 73 )} 74 </Header> 75 <Description description={view.description} /> 76 </Outer> 77 </Link> 78 ) 79} 80 81export function Link({ 82 view, 83 children, 84 ...props 85}: Props & Omit<LinkProps, 'to' | 'label'>) { 86 const queryClient = useQueryClient() 87 88 const href = React.useMemo(() => { 89 return createProfileListHref({list: view}) 90 }, [view]) 91 92 React.useEffect(() => { 93 precacheList(queryClient, view) 94 }, [view, queryClient]) 95 96 return ( 97 <InternalLink label={view.name} to={href} {...props}> 98 {children} 99 </InternalLink> 100 ) 101} 102 103export function TitleAndByline({ 104 title, 105 creator, 106 purpose = CURATELIST, 107 modUi, 108}: { 109 title: string 110 creator?: bsky.profile.AnyProfileView 111 purpose?: AppBskyGraphDefs.ListView['purpose'] 112 modUi?: ModerationUI 113}) { 114 const t = useTheme() 115 const {_} = useLingui() 116 const {currentAccount} = useSession() 117 118 return ( 119 <View style={[a.flex_1]}> 120 <Hider.Outer 121 modui={modUi} 122 isContentVisibleInitialState={ 123 creator && currentAccount?.did === creator.did 124 } 125 allowOverride={creator && currentAccount?.did === creator.did}> 126 <Hider.Mask> 127 <Text 128 style={[a.text_md, a.font_bold, a.leading_snug, a.italic]} 129 numberOfLines={1}> 130 <Trans>Hidden list</Trans> 131 </Text> 132 </Hider.Mask> 133 <Hider.Content> 134 <Text 135 emoji 136 style={[a.text_md, a.font_bold, a.leading_snug]} 137 numberOfLines={1}> 138 {title} 139 </Text> 140 </Hider.Content> 141 </Hider.Outer> 142 143 {creator && ( 144 <Text 145 emoji 146 style={[a.leading_snug, t.atoms.text_contrast_medium]} 147 numberOfLines={1}> 148 {purpose === MODLIST 149 ? _(msg`Moderation list by ${sanitizeHandle(creator.handle, '@')}`) 150 : _(msg`List by ${sanitizeHandle(creator.handle, '@')}`)} 151 </Text> 152 )} 153 </View> 154 ) 155} 156 157export function createProfileListHref({ 158 list, 159}: { 160 list: AppBskyGraphDefs.ListView 161}) { 162 const urip = new AtUri(list.uri) 163 const handleOrDid = list.creator.handle || list.creator.did 164 return `/profile/${handleOrDid}/lists/${urip.rkey}` 165}