src
webapp
features
platforms
bluesky
components
blueskyPost
externalEmbed
listEmbed
postEmbed
starterPackEmbed
videoEmbed
lib
···
46
46
</Group>
47
47
<Stack gap={'xs'}>
48
48
<Box>
49
49
-
<RichTextRenderer text={record.text} textProps={{ lineClamp: 4 }} />
49
49
+
<RichTextRenderer text={record.text} textProps={{ lineClamp: 3 }} />
50
50
</Box>
51
51
{post.embed && <PostEmbed embed={post.embed} />}
52
52
</Stack>
···
19
19
<CardSection>
20
20
{props.embed.external.thumb && (
21
21
<AspectRatio ratio={16 / 9}>
22
22
-
<Image src={props.embed.external.thumb} />
22
22
+
<Image
23
23
+
src={props.embed.external.thumb}
24
24
+
alt={props.embed.external.description}
25
25
+
/>
23
26
</AspectRatio>
24
27
)}
25
28
</CardSection>
26
29
27
27
-
<Stack gap={0} p={"xs"}>
30
30
+
<Stack gap={0} p={'xs'}>
28
31
<Text fz={'sm'} fw={500} c={'bright'} lineClamp={1}>
29
32
{props.embed.external.title}
30
33
</Text>
···
1
1
+
import { AppBskyGraphDefs } from '@atproto/api';
2
2
+
import { BsFillPeopleFill } from 'react-icons/bs';
3
3
+
import { Card, Group, Text } from '@mantine/core';
4
4
+
5
5
+
interface Props {
6
6
+
list: AppBskyGraphDefs.ListView;
7
7
+
}
8
8
+
9
9
+
export default function ListEmbed(props: Props) {
10
10
+
const { list } = props;
11
11
+
12
12
+
return (
13
13
+
<Card withBorder>
14
14
+
<Group gap={'xs'}>
15
15
+
<BsFillPeopleFill />
16
16
+
<Text fz={'sm'} fw={500} c={'bright'} lineClamp={1}>
17
17
+
{list.name}
18
18
+
</Text>
19
19
+
</Group>
20
20
+
<Text fz={'sm'} fw={500} c={'gray'} lineClamp={1} span>
21
21
+
@{list.creator.handle}
22
22
+
</Text>
23
23
+
</Card>
24
24
+
);
25
25
+
}
···
1
1
import {
2
2
AppBskyEmbedExternal,
3
3
AppBskyEmbedImages,
4
4
+
AppBskyEmbedRecord,
5
5
+
AppBskyEmbedVideo,
4
6
AppBskyFeedDefs,
7
7
+
AppBskyGraphDefs,
5
8
} from '@atproto/api';
6
9
import ImageEmbed from '../imageEmbed/ImageEmbed';
7
10
import ExternalEmbed from '../externalEmbed/ExternalEmbed';
11
11
+
import VideoEmbed from '../videoEmbed/VideoEmbed';
12
12
+
import ListEmbed from '../listEmbed/ListEmbed';
8
13
9
14
interface Props {
10
10
-
embed: AppBskyFeedDefs.FeedViewPost['post']['embed'];
15
15
+
embed: AppBskyFeedDefs.PostView['embed'];
11
16
}
17
17
+
12
18
export default function PostEmbed(props: Props) {
19
19
+
const content = props.embed;
20
20
+
13
21
switch (true) {
14
14
-
case AppBskyEmbedImages.isView(props.embed):
15
15
-
return <ImageEmbed images={props.embed.images} />;
16
16
-
case AppBskyEmbedExternal.isView(props.embed):
17
17
-
return <ExternalEmbed embed={props.embed} />;
22
22
+
case AppBskyEmbedImages.isView(content):
23
23
+
return <ImageEmbed images={content.images} />;
24
24
+
case AppBskyEmbedExternal.isView(content):
25
25
+
return <ExternalEmbed embed={content} />;
26
26
+
case AppBskyEmbedVideo.isView(content):
27
27
+
return <VideoEmbed embed={content} />;
28
28
+
case AppBskyEmbedRecord.isView(content) &&
29
29
+
AppBskyGraphDefs.isListView(content.record):
30
30
+
return <ListEmbed list={content.record} />;
31
31
+
18
32
default:
19
33
return <>default</>;
20
34
}
···
1
1
+
import { AppBskyGraphDefs, AppBskyGraphStarterpack } from '@atproto/api';
2
2
+
import { Card, CardSection, Image, Text } from '@mantine/core';
3
3
+
import { getStarterPackImage } from '../../lib/utils/link';
4
4
+
5
5
+
interface Props {
6
6
+
embed: AppBskyGraphDefs.StarterPackViewBasic;
7
7
+
}
8
8
+
9
9
+
export default function StarterPackEmbed(props: Props) {
10
10
+
if (!AppBskyGraphStarterpack.isRecord(props.embed.record)) {
11
11
+
return null;
12
12
+
}
13
13
+
14
14
+
const image = getStarterPackImage(props.embed);
15
15
+
return (
16
16
+
<Card>
17
17
+
{image && (
18
18
+
<CardSection>
19
19
+
<Image src={image} />
20
20
+
</CardSection>
21
21
+
)}
22
22
+
<Text fz={'sm'} fw={500} c={'gray'} lineClamp={1}>
23
23
+
By {props.embed.creator.handle}
24
24
+
</Text>
25
25
+
</Card>
26
26
+
);
27
27
+
}
···
1
1
+
import { AppBskyEmbedVideo } from '@atproto/api';
2
2
+
import { AspectRatio, Image } from '@mantine/core';
3
3
+
4
4
+
interface Props {
5
5
+
embed: AppBskyEmbedVideo.View;
6
6
+
}
7
7
+
8
8
+
export default function VideoEmbed(props: Props) {
9
9
+
return (
10
10
+
<AspectRatio ratio={16 / 9}>
11
11
+
<Image src={props.embed.thumbnail} alt={props.embed.alt} radius={'sm'} />
12
12
+
</AspectRatio>
13
13
+
);
14
14
+
}
···
1
1
+
import { AppBskyGraphDefs, AtUri } from '@atproto/api';
2
2
+
3
3
+
export const getStarterPackImage = (
4
4
+
starterPack: AppBskyGraphDefs.StarterPackViewBasic,
5
5
+
) => {
6
6
+
const rkey = new AtUri(starterPack.uri).rkey;
7
7
+
return `https://ogcard.cdn.bsky.app/start/${starterPack.creator.did}/${rkey}`;
8
8
+
};