feat: retrieve images

This commit is contained in:
Julien Calixte
2026-02-14 00:17:16 +01:00
parent 7ab4d64dea
commit 33eeb9ae02
2 changed files with 36 additions and 10 deletions

View File

@@ -1,27 +1,33 @@
const correspondanceCache = new Map<string, string>() type Author = { alias: string; endpoint: string }
export const getUniqueAka = async (did: string) => { const correspondanceCache = new Map<string, Author>()
export const getUniqueAka = async (did: string): Promise<Author> => {
console.log(correspondanceCache)
if (correspondanceCache.has(did)) { 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 response = await fetch(`https://plc.directory/${did}`)
const { const {
alsoKnownAs: [aka], alsoKnownAs: [aka],
service: [{ serviceEndpoint }],
} = await response.json() } = await response.json()
const alias = aka.replace("at://", "") 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<string>) => { export const getAka = async (dids: Set<string>) => {
const correspondance = await Promise.all( const correspondance = await Promise.all(
[...dids].map(async (did) => { [...dids].map(async (did) => {
if (correspondanceCache.has(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}`) const response = await fetch(`https://plc.directory/${did}`)

View File

@@ -42,7 +42,7 @@ const did = computed(() => props.did)
const rkey = computed(() => props.rkey) const rkey = computed(() => props.rkey)
const { scrollToFocusedNote } = useRouteQueryStackedNotes() const { scrollToFocusedNote } = useRouteQueryStackedNotes()
const alias = computedAsync(async () => getUniqueAka(did.value)) const author = computedAsync(async () => getUniqueAka(did.value))
const url = computedAsync(async () => const url = computedAsync(async () =>
getUrl({ did: did.value, rkey: rkey.value }), 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<Root>) : null, url.value ? ((await fetch(url.value).then()).json() as Promise<Root>) : null,
) )
const { toHTML } = markdownBuilder() 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 title = computed(() => rawContent.value?.value.title)
const content = computed(() => const content = computed(() =>
rawContent.value?.value.content rawContent.value?.value.content
? toHTML(rawContent.value?.value.content) ? toHTML(withATProtoImages(rawContent.value?.value.content))
: "", : "",
) )
</script> </script>
@@ -66,11 +82,11 @@ const content = computed(() =>
<a <a
class="title-stacked-note-link" class="title-stacked-note-link"
@click.prevent="scrollToFocusedNote()" @click.prevent="scrollToFocusedNote()"
v-if="alias && title" v-if="author && title"
>{{ title }}</a >{{ title }}</a
> >
</div> </div>
<span class="badge badge-accent">{{ alias }}</span> <span class="badge badge-accent" v-if="author">{{ author.alias }}</span>
<article v-html="content"></article> <article v-html="content"></article>
</div> </div>
</div> </div>
@@ -81,6 +97,10 @@ const content = computed(() =>
display: flex; display: flex;
flex: 1; flex: 1;
.badge {
margin-bottom: 1rem;
}
.article { .article {
position: sticky; position: sticky;
left: 0; left: 0;