import { $Typed, is$typed } from "@atproto/api/dist/client/util"; import { AppBskyEmbedImages, AppBskyEmbedVideo, AppBskyEmbedExternal, AppBskyEmbedRecord, AppBskyEmbedRecordWithMedia, AppBskyFeedPost, AppBskyFeedDefs, AppBskyGraphDefs, AppBskyLabelerDefs, } from "@atproto/api"; export const BlueskyEmbed = (props: { embed: Exclude; postUrl?: string; }) => { // check this file from bluesky for ref // https://github.com/bluesky-social/social-app/blob/main/bskyembed/src/components/embed.tsx switch (true) { case AppBskyEmbedImages.isView(props.embed): let imageEmbed = props.embed; return (
{imageEmbed.images.map( (image: { fullsize: string; alt?: string }, i: number) => ( {image.alt ), )}
); case AppBskyEmbedExternal.isView(props.embed): let externalEmbed = props.embed; let isGif = externalEmbed.external.uri.includes(".gif"); if (isGif) { return (
{externalEmbed.external.title}
); } return ( {externalEmbed.external.thumb === undefined ? null : ( <> {externalEmbed.external.title}
)}

{externalEmbed.external.title}

{externalEmbed.external.description}


{externalEmbed.external.uri}
); case AppBskyEmbedVideo.isView(props.embed): let videoEmbed = props.embed; return (
{
); case AppBskyEmbedRecord.isView(props.embed): let recordEmbed = props.embed; let record = recordEmbed.record; if (record === undefined) return; // if the record is a feed post if (AppBskyEmbedRecord.isViewRecord(record)) { // we have to do this nonsense to get a the proper type for the record text // we aped it from the bluesky front end (check the link at the top of this file) let text: string | null = null; if (AppBskyFeedPost.isRecord(record.value)) { text = (record.value as AppBskyFeedPost.Record).text; } return (
{record.author.avatar && ( {`${record.author?.displayName}'s )}
{record.author?.displayName}
@{record.author?.handle}
{text &&
{text}
} {record.embeds !== undefined ? record.embeds.map((embed, index) => ( )) : null}
); } // labeller, starterpack or feed if ( AppBskyFeedDefs.isGeneratorView(record) || AppBskyLabelerDefs.isLabelerView(record) || AppBskyGraphDefs.isStarterPackViewBasic(record) ) return ; // post is blocked or not found if ( AppBskyFeedDefs.isBlockedPost(record) || AppBskyFeedDefs.isNotFoundPost(record) ) return ; if (AppBskyEmbedRecord.isViewDetached(record)) return null; return ; // I am not sure when this case will be used? so I'm commenting it out for now case AppBskyEmbedRecordWithMedia.isView(props.embed) && AppBskyEmbedRecord.isViewRecord(props.embed.record.record): return (
); default: return ; } }; const SeePostOnBluesky = (props: { postUrl: string | undefined }) => { return (
This media is not supported...
{" "} {props.postUrl === undefined ? null : (
See the full post on Bluesky!
)}
); }; export const PostNotAvailable = () => { return (
This Bluesky post is not available...
); };