From 33eeb9ae02b211b7d493490dc2b020df4878bd79 Mon Sep 17 00:00:00 2001 From: Julien Calixte Date: Sat, 14 Feb 2026 00:17:16 +0100 Subject: [PATCH] feat: retrieve images --- src/modules/atproto/getAka.ts | 18 ++++++++++++------ src/views/PublicNoteView.vue | 28 ++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/modules/atproto/getAka.ts b/src/modules/atproto/getAka.ts index 233940b..dfa21f4 100644 --- a/src/modules/atproto/getAka.ts +++ b/src/modules/atproto/getAka.ts @@ -1,27 +1,33 @@ -const correspondanceCache = new Map() +type Author = { alias: string; endpoint: string } -export const getUniqueAka = async (did: string) => { +const correspondanceCache = new Map() + +export const getUniqueAka = async (did: string): Promise => { + console.log(correspondanceCache) if (correspondanceCache.has(did)) { - return correspondanceCache.get(did) as string + return correspondanceCache.get(did) as Author } const response = await fetch(`https://plc.directory/${did}`) const { alsoKnownAs: [aka], + service: [{ serviceEndpoint }], } = await response.json() const alias = aka.replace("at://", "") + const author = { alias, endpoint: serviceEndpoint } - correspondanceCache.set(did, alias) + correspondanceCache.set(did, author) + console.log(correspondanceCache) - return alias + return author } export const getAka = async (dids: Set) => { const correspondance = await Promise.all( [...dids].map(async (did) => { if (correspondanceCache.has(did)) { - return [did, correspondanceCache.get(did)!] as [string, string] + return [did, correspondanceCache.get(did)?.alias] as [string, string] } const response = await fetch(`https://plc.directory/${did}`) diff --git a/src/views/PublicNoteView.vue b/src/views/PublicNoteView.vue index 6505a92..c018e0a 100644 --- a/src/views/PublicNoteView.vue +++ b/src/views/PublicNoteView.vue @@ -42,7 +42,7 @@ const did = computed(() => props.did) const rkey = computed(() => props.rkey) const { scrollToFocusedNote } = useRouteQueryStackedNotes() -const alias = computedAsync(async () => getUniqueAka(did.value)) +const author = computedAsync(async () => getUniqueAka(did.value)) const url = computedAsync(async () => getUrl({ did: did.value, rkey: rkey.value }), ) @@ -50,11 +50,27 @@ const rawContent = computedAsync(async () => url.value ? ((await fetch(url.value).then()).json() as Promise) : null, ) const { toHTML } = markdownBuilder() +const withATProtoImages = (markdown: string) => { + if (!author.value) { + return markdown + } + + const endpoint = author.value.endpoint + + const imageLinkPattern = /!\[([^\]]*)\]\((bafkrei[a-z0-9]+)\)/g + + return markdown.replace(imageLinkPattern, (_, altText, cid) => { + const imageUrl = new URL("/xrpc/com.atproto.sync.getBlob", endpoint) + imageUrl.searchParams.set("did", did.value) + imageUrl.searchParams.set("cid", cid) + return `![${altText}](${imageUrl.toString()})` + }) +} const title = computed(() => rawContent.value?.value.title) const content = computed(() => rawContent.value?.value.content - ? toHTML(rawContent.value?.value.content) + ? toHTML(withATProtoImages(rawContent.value?.value.content)) : "", ) @@ -66,11 +82,11 @@ const content = computed(() => {{ title }} - {{ alias }} + {{ author.alias }}
@@ -81,6 +97,10 @@ const content = computed(() => display: flex; flex: 1; + .badge { + margin-bottom: 1rem; + } + .article { position: sticky; left: 0;