This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

semble / src / webapp / features / platforms / bluesky / components / blueskyPost / BlueskyPost.tsx
3.2 kB 109 lines
1'use client'; 2 3import { AppBskyFeedDefs, AppBskyFeedPost } from '@atproto/api'; 4import { ReactElement } from 'react'; 5import { 6 Group, 7 Stack, 8 Text, 9 Avatar, 10 Box, 11 Image, 12 Anchor, 13 Tooltip, 14} from '@mantine/core'; 15import RichTextRenderer from '@/components/contentDisplay/richTextRenderer/RichTextRenderer'; 16import useGetBlueskyPost from '../../lib/queries/useGetBlueskyPost'; 17import PostEmbed from '../postEmbed/PostEmbed'; 18import { FaBluesky } from 'react-icons/fa6'; 19import { detectUrlPlatform, SupportedPlatform } from '@/lib/utils/link'; 20import { getPostUriFromUrl } from '@/lib/utils/atproto'; 21import BlackskyLogo from '@/assets/icons/blacksky-logo.svg'; 22import BlackskyLogoWhite from '@/assets/icons/blacksky-logo-white.svg'; 23import { useUserSettings } from '@/features/settings/lib/queries/useUserSettings'; 24 25interface Props { 26 url: string; 27 fallbackCardContent: ReactElement; 28} 29 30export default function BlueskyPost(props: Props) { 31 const { settings } = useUserSettings(); 32 const uri = getPostUriFromUrl(props.url); 33 const { data, error } = useGetBlueskyPost({ uri }); 34 const showEmbed = settings.cardView !== 'list'; 35 const platform = detectUrlPlatform(props.url); 36 const platformIcon = 37 platform.type === SupportedPlatform.BLUESKY_POST ? ( 38 <FaBluesky fill="#0085ff" size={18} /> 39 ) : ( 40 <> 41 <Image 42 src={BlackskyLogo.src} 43 alt="Blacksky logo" 44 w={18} 45 h={'auto'} 46 darkHidden 47 /> 48 <Image 49 src={BlackskyLogoWhite.src} 50 alt="Blacksky logo" 51 w={18} 52 h={'auto'} 53 lightHidden 54 /> 55 </> 56 ); 57 58 if ( 59 !data.thread || 60 !AppBskyFeedDefs.isThreadViewPost(data.thread) || 61 AppBskyFeedDefs.isNotFoundPost(data.thread.post) || 62 AppBskyFeedDefs.isBlockedPost(data.thread.post) || 63 error 64 ) { 65 return props.fallbackCardContent; 66 } 67 68 const post = data.thread.post; 69 const record = post.record as AppBskyFeedPost.Record; 70 71 return ( 72 <Stack justify="space-between" gap="xs"> 73 <Group gap="xs" justify="space-between" wrap="nowrap" w={'100%'}> 74 <Group gap={'xs'} wrap="nowrap"> 75 <Avatar 76 src={post.author.avatar?.replace('avatar', 'avatar_thumbnail')} 77 alt={`${post.author.handle} avatar`} 78 size={'sm'} 79 radius="xl" 80 /> 81 82 <Text c="bright" lineClamp={1} fw={500}> 83 {post.author.displayName || post.author.handle} 84 </Text> 85 </Group> 86 <Tooltip 87 label={`View on ${platform.type === SupportedPlatform.BLUESKY_POST ? 'Bluesky' : 'Blacksky'}`} 88 > 89 <Anchor 90 href={props.url} 91 target="_blank" 92 onClick={(e) => e.stopPropagation()} 93 > 94 {platformIcon} 95 </Anchor> 96 </Tooltip> 97 </Group> 98 <Stack gap={'xs'} w={'100%'}> 99 <Box> 100 <RichTextRenderer 101 text={record.text} 102 textProps={{ lineClamp: settings.cardView === 'list' ? 1 : 3 }} 103 /> 104 </Box> 105 {post.embed && showEmbed && <PostEmbed embed={post.embed} />} 106 </Stack> 107 </Stack> 108 ); 109}