Add parseEmbed utils

This commit is contained in:
Eric Bailey
2025-01-06 15:44:04 -06:00
parent e23ce16ff2
commit 55055c1cd0
2 changed files with 150 additions and 17 deletions
+14 -17
View File
@@ -1,13 +1,7 @@
import React from 'react' import React from 'react'
import {StyleProp, StyleSheet, View, ViewStyle} from 'react-native' import {StyleProp, StyleSheet, View, ViewStyle} from 'react-native'
import {Image} from 'expo-image' import {Image} from 'expo-image'
import { import {AppBskyFeedDefs} from '@atproto/api'
AppBskyEmbedExternal,
AppBskyEmbedImages,
AppBskyEmbedRecordWithMedia,
AppBskyEmbedVideo,
AppBskyFeedDefs,
} from '@atproto/api'
import {Trans} from '@lingui/macro' import {Trans} from '@lingui/macro'
import {parseTenorGif} from '#/lib/strings/embed-player' import {parseTenorGif} from '#/lib/strings/embed-player'
@@ -15,6 +9,7 @@ import {atoms as a, useTheme} from '#/alf'
import {MediaInsetBorder} from '#/components/MediaInsetBorder' import {MediaInsetBorder} from '#/components/MediaInsetBorder'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
import {PlayButtonIcon} from '#/components/video/PlayButtonIcon' import {PlayButtonIcon} from '#/components/video/PlayButtonIcon'
import {parseEmbed} from '#/types/atproto/post'
/** /**
* Streamlined MediaPreview component which just handles images, gifs, and videos * Streamlined MediaPreview component which just handles images, gifs, and videos
@@ -23,15 +18,17 @@ export function Embed({
embed, embed,
style, style,
}: { }: {
embed?: AppBskyFeedDefs.PostView['embed'] embed: AppBskyFeedDefs.PostView['embed']
style?: StyleProp<ViewStyle> style?: StyleProp<ViewStyle>
}) { }) {
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 ( return (
<Outer style={style}> <Outer style={style}>
{media.images.map(image => ( {e.view.images.map(image => (
<ImageItem <ImageItem
key={image.thumb} key={image.thumb}
thumbnail={image.thumb} thumbnail={image.thumb}
@@ -40,10 +37,10 @@ export function Embed({
))} ))}
</Outer> </Outer>
) )
} else if (AppBskyEmbedExternal.isValidView(media) && media.external.thumb) { } else if (e.type === 'link' && e.view.external.thumb) {
let url: URL | undefined let url: URL | undefined
try { try {
url = new URL(media.external.uri) url = new URL(e.view.external.uri)
} catch {} } catch {}
if (url) { if (url) {
const {success} = parseTenorGif(url) const {success} = parseTenorGif(url)
@@ -51,17 +48,17 @@ export function Embed({
return ( return (
<Outer style={style}> <Outer style={style}>
<GifItem <GifItem
thumbnail={media.external.thumb} thumbnail={e.view.external.thumb}
alt={media.external.title} alt={e.view.external.title}
/> />
</Outer> </Outer>
) )
} }
} }
} else if (AppBskyEmbedVideo.isValidView(media)) { } else if (e.type === 'video') {
return ( return (
<Outer style={style}> <Outer style={style}>
<VideoItem thumbnail={media.thumbnail} alt={media.alt} /> <VideoItem thumbnail={e.view.thumbnail} alt={e.view.alt} />
</Outer> </Outer>
) )
} }
+136
View File
@@ -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),
}
}
}