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