diff --git a/src/components/MediaPreview.tsx b/src/components/MediaPreview.tsx index 0d5ef05fc8..9d9c755456 100644 --- a/src/components/MediaPreview.tsx +++ b/src/components/MediaPreview.tsx @@ -1,13 +1,7 @@ import React from 'react' import {StyleProp, StyleSheet, View, ViewStyle} from 'react-native' import {Image} from 'expo-image' -import { - AppBskyEmbedExternal, - AppBskyEmbedImages, - AppBskyEmbedRecordWithMedia, - AppBskyEmbedVideo, - AppBskyFeedDefs, -} from '@atproto/api' +import {AppBskyFeedDefs} from '@atproto/api' import {Trans} from '@lingui/macro' import {parseTenorGif} from '#/lib/strings/embed-player' @@ -15,6 +9,7 @@ import {atoms as a, useTheme} from '#/alf' import {MediaInsetBorder} from '#/components/MediaInsetBorder' import {Text} from '#/components/Typography' import {PlayButtonIcon} from '#/components/video/PlayButtonIcon' +import {parseEmbed} from '#/types/atproto/post' /** * Streamlined MediaPreview component which just handles images, gifs, and videos @@ -23,15 +18,17 @@ export function Embed({ embed, style, }: { - embed?: AppBskyFeedDefs.PostView['embed'] + embed: AppBskyFeedDefs.PostView['embed'] style?: StyleProp }) { - let media = AppBskyEmbedRecordWithMedia.isView(embed) ? embed.media : embed + const e = parseEmbed(embed) - if (AppBskyEmbedImages.isValidView(media)) { + if (!e) return null + + if (e.type === 'images') { return ( - {media.images.map(image => ( + {e.view.images.map(image => ( ) - } else if (AppBskyEmbedExternal.isValidView(media) && media.external.thumb) { + } else if (e.type === 'link' && e.view.external.thumb) { let url: URL | undefined try { - url = new URL(media.external.uri) + url = new URL(e.view.external.uri) } catch {} if (url) { const {success} = parseTenorGif(url) @@ -51,17 +48,17 @@ export function Embed({ return ( ) } } - } else if (AppBskyEmbedVideo.isValidView(media)) { + } else if (e.type === 'video') { return ( - + ) } diff --git a/src/types/atproto/post.ts b/src/types/atproto/post.ts new file mode 100644 index 0000000000..ffd6eb47d2 --- /dev/null +++ b/src/types/atproto/post.ts @@ -0,0 +1,136 @@ +import { + AppBskyEmbedExternal, + AppBskyEmbedImages, + AppBskyEmbedRecord, + AppBskyEmbedRecordWithMedia, + AppBskyEmbedVideo, + AppBskyFeedDefs, + AppBskyGraphDefs, + AppBskyLabelerDefs, +} from '@atproto/api' + +export type View = + | { + type: 'post' + view: AppBskyEmbedRecord.ViewRecord + } + | { + type: 'post_not_found' + view: AppBskyEmbedRecord.ViewNotFound + } + | { + type: 'post_blocked' + view: AppBskyEmbedRecord.ViewBlocked + } + | { + type: 'post_detached' + view: AppBskyEmbedRecord.ViewDetached + } + | { + type: 'feed' + view: AppBskyFeedDefs.GeneratorView + } + | { + type: 'list' + view: AppBskyGraphDefs.ListView + } + | { + type: 'labeler' + view: AppBskyLabelerDefs.LabelerView + } + | { + type: 'starter_pack' + view: AppBskyGraphDefs.StarterPackViewBasic + } + | { + type: 'images' + view: AppBskyEmbedImages.View + } + | { + type: 'link' + view: AppBskyEmbedExternal.View + } + | { + type: 'video' + view: AppBskyEmbedVideo.View + } + | { + type: 'post_with_media' + view: View | undefined + media: View | undefined + } + +export function parseEmbedView( + view: AppBskyEmbedRecord.View, +): View | undefined { + if (AppBskyEmbedRecord.isViewRecord(view.record)) { + return { + type: 'post', + view: view.record, + } + } else if (AppBskyEmbedRecord.isViewNotFound(view.record)) { + return { + type: 'post_not_found', + view: view.record, + } + } else if (AppBskyEmbedRecord.isViewBlocked(view.record)) { + return { + type: 'post_blocked', + view: view.record, + } + } else if (AppBskyEmbedRecord.isViewDetached(view.record)) { + return { + type: 'post_detached', + view: view.record, + } + } else if (AppBskyFeedDefs.isGeneratorView(view.record)) { + return { + type: 'feed', + view: view.record, + } + } else if (AppBskyGraphDefs.isListView(view.record)) { + return { + type: 'list', + view: view.record, + } + } else if (AppBskyLabelerDefs.isLabelerView(view.record)) { + return { + type: 'labeler', + view: view.record, + } + } else if (AppBskyGraphDefs.isStarterPackViewBasic(view.record)) { + return { + type: 'starter_pack', + view: view.record, + } + } +} + +export function parseEmbed( + embed: AppBskyFeedDefs.PostView['embed'], +): View | undefined { + if (AppBskyEmbedImages.isView(embed)) { + return { + type: 'images', + view: embed, + } + } else if (AppBskyEmbedExternal.isView(embed)) { + return { + type: 'link', + view: embed, + } + } else if (AppBskyEmbedVideo.isView(embed)) { + return { + type: 'video', + view: embed, + } + } else if (AppBskyEmbedRecord.isView(embed)) { + return parseEmbedView(embed) + } else if (AppBskyEmbedRecordWithMedia.isView(embed)) { + return { + type: 'post_with_media', + view: parseEmbedView(embed.record), + media: parseEmbed(embed.media), + } + } +}