diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/link-meta/bsky.ts | 30 | ||||
-rw-r--r-- | src/lib/strings/url-helpers.ts | 12 | ||||
-rw-r--r-- | src/view/com/composer/ComposePost.tsx | 41 |
3 files changed, 73 insertions, 10 deletions
diff --git a/src/lib/link-meta/bsky.ts b/src/lib/link-meta/bsky.ts index fba41260d..c9c2ed31a 100644 --- a/src/lib/link-meta/bsky.ts +++ b/src/lib/link-meta/bsky.ts @@ -3,6 +3,7 @@ import {match as matchRoute} from 'view/routes' import {convertBskyAppUrlIfNeeded, makeRecordUri} from '../strings/url-helpers' import {RootStoreModel} from 'state/index' import {PostThreadViewModel} from 'state/models/post-thread-view' +import {ComposerOptsQuote} from 'state/models/shell-ui' import {Home} from 'view/screens/Home' import {Search} from 'view/screens/Search' @@ -97,3 +98,32 @@ export async function extractBskyMeta( return meta } + +export async function getPostAsQuote( + store: RootStoreModel, + url: string, +): Promise<ComposerOptsQuote> { + url = convertBskyAppUrlIfNeeded(url) + const [_0, user, _1, rkey] = url.split('/').filter(Boolean) + const threadUri = makeRecordUri(user, 'app.bsky.feed.post', rkey) + + const threadView = new PostThreadViewModel(store, { + uri: threadUri, + depth: 0, + }) + await threadView.setup() + if (!threadView.thread || threadView.notFound) { + throw new Error('Not found') + } + return { + uri: threadView.thread.post.uri, + cid: threadView.thread.post.cid, + text: threadView.thread.postRecord?.text || '', + indexedAt: threadView.thread.post.indexedAt, + author: { + handle: threadView.thread.post.author.handle, + displayName: threadView.thread.post.author.displayName, + avatar: threadView.thread.post.author.avatar, + }, + } +} diff --git a/src/lib/strings/url-helpers.ts b/src/lib/strings/url-helpers.ts index a149f49c3..1fa30a3ef 100644 --- a/src/lib/strings/url-helpers.ts +++ b/src/lib/strings/url-helpers.ts @@ -66,6 +66,18 @@ export function isBskyAppUrl(url: string): boolean { return url.startsWith('https://bsky.app/') } +export function isBskyPostUrl(url: string): boolean { + if (isBskyAppUrl(url)) { + try { + const urlp = new URL(url) + return /profile\/(?<name>[^/]+)\/post\/(?<rkey>[^/]+)/i.test( + urlp.pathname, + ) + } catch {} + } + return false +} + export function convertBskyAppUrlIfNeeded(url: string): string { if (isBskyAppUrl(url)) { try { diff --git a/src/view/com/composer/ComposePost.tsx b/src/view/com/composer/ComposePost.tsx index a7c5711aa..f45c6340d 100644 --- a/src/view/com/composer/ComposePost.tsx +++ b/src/view/com/composer/ComposePost.tsx @@ -36,10 +36,12 @@ import {s, colors, gradients} from 'lib/styles' import {cleanError} from 'lib/strings/errors' import {detectLinkables, extractEntities} from 'lib/strings/rich-text-detection' import {getLinkMeta} from 'lib/link-meta/link-meta' +import {getPostAsQuote} from 'lib/link-meta/bsky' import {getImageDim, downloadAndResize} from 'lib/media/manip' import {PhotoCarouselPicker} from './photos/PhotoCarouselPicker' import {cropAndCompressFlow, pickImagesFlow} from '../../../lib/media/picker' import {getMentionAt, insertMentionAt} from 'lib/strings/mention-manip' +import {isBskyPostUrl} from 'lib/strings/url-helpers' import {SelectedPhoto} from './SelectedPhoto' import {usePalette} from 'lib/hooks/usePalette' import { @@ -63,7 +65,7 @@ export const ComposePost = observer(function ComposePost({ imagesOpen, onPost, onClose, - quote, + quote: initQuote, }: { replyTo?: ComposerOpts['replyTo'] imagesOpen?: ComposerOpts['imagesOpen'] @@ -80,6 +82,9 @@ export const ComposePost = observer(function ComposePost({ const [processingState, setProcessingState] = useState('') const [error, setError] = useState('') const [text, setText] = useState('') + const [quote, setQuote] = useState<ComposerOpts['quote'] | undefined>( + initQuote, + ) const [extLink, setExtLink] = useState<apilib.ExternalEmbedDraft | undefined>( undefined, ) @@ -121,16 +126,32 @@ export const ComposePost = observer(function ComposePost({ return cleanup } if (!extLink.meta) { - getLinkMeta(store, extLink.uri).then(meta => { - if (aborted) { - return - } - setExtLink({ - uri: extLink.uri, - isLoading: !!meta.image, - meta, + if (isBskyPostUrl(extLink.uri)) { + getPostAsQuote(store, extLink.uri).then( + newQuote => { + if (aborted) { + return + } + setQuote(newQuote) + setExtLink(undefined) + }, + err => { + store.log.error('Failed to fetch post for quote embedding', {err}) + setExtLink(undefined) + }, + ) + } else { + getLinkMeta(store, extLink.uri).then(meta => { + if (aborted) { + return + } + setExtLink({ + uri: extLink.uri, + isLoading: !!meta.image, + meta, + }) }) - }) + } return cleanup } if (extLink.isLoading && extLink.meta?.image && !extLink.localThumb) { |