diff --git a/src/bus/publicNoteEventBus.ts b/src/bus/publicNoteEventBus.ts
index 341842b..d5537c1 100644
--- a/src/bus/publicNoteEventBus.ts
+++ b/src/bus/publicNoteEventBus.ts
@@ -1,7 +1,7 @@
import { createEventBus } from "retrobus"
interface EventBusParams {
- path: string
+ atUri: string
currentNoteRkey?: string
}
diff --git a/src/components/StackedPublicNote.vue b/src/components/StackedPublicNote.vue
new file mode 100644
index 0000000..0621152
--- /dev/null
+++ b/src/components/StackedPublicNote.vue
@@ -0,0 +1,191 @@
+
+
+
+
+
+
+
diff --git a/src/hooks/useATProtoLinks.hook.ts b/src/hooks/useATProtoLinks.hook.ts
index 87baa09..59de63b 100644
--- a/src/hooks/useATProtoLinks.hook.ts
+++ b/src/hooks/useATProtoLinks.hook.ts
@@ -1,36 +1,34 @@
import { ComputedRef, onUnmounted, Ref, toValue } from "vue"
import { isExternalLink } from "@/utils/link"
-import { publicNoteEventBus } from "@/bus/publicNoteEventBus"
+import { useRouteQueryStackedNotes } from "@/hooks/useRouteQueryStackedNotes.hook"
export const useATProtoLinks = (
className: ComputedRef | string,
- rkey?: Ref | string,
+ currentAtUri?: Ref | string,
) => {
+ const { addStackedNote } = useRouteQueryStackedNotes()
const linkNote: EventListener = (event) => {
const target = event.target as HTMLElement
- const href = target.getAttribute("href")
+ const atUri = target.getAttribute("href")
- if (!href) {
+ if (!atUri) {
return
}
- if (href.startsWith("#")) {
+ if (atUri.startsWith("#")) {
return
}
event.preventDefault()
event.stopPropagation()
- if (isExternalLink(href)) {
- window.open(href, "_blank")
+ if (isExternalLink(atUri)) {
+ window.open(atUri, "_blank")
return
}
- publicNoteEventBus.emit({
- path: href,
- currentNoteRkey: toValue(rkey),
- })
+ addStackedNote(toValue(currentAtUri) ?? "", atUri)
}
const LINK_SELECTOR = `.${toValue(className)} a`
diff --git a/src/modules/atproto/getAka.ts b/src/modules/atproto/getAka.ts
index e83ce5d..e6b8628 100644
--- a/src/modules/atproto/getAka.ts
+++ b/src/modules/atproto/getAka.ts
@@ -2,8 +2,6 @@ export type Author = { alias: string; endpoint: string }
const correspondanceCache = new Map()
-console.log({ correspondanceCache })
-
export const getUniqueAka = async (did: string): Promise => {
if (correspondanceCache.has(did)) {
return correspondanceCache.get(did) as Author
diff --git a/src/modules/atproto/parseAtUri.ts b/src/modules/atproto/parseAtUri.ts
new file mode 100644
index 0000000..64595b0
--- /dev/null
+++ b/src/modules/atproto/parseAtUri.ts
@@ -0,0 +1,7 @@
+export const parseAtUri = (atUri: string): { did: string; rkey: string } => {
+ const match = atUri.match(/^at:\/\/(did:[^/]+)\/[^/]+\/(.+)$/)
+ if (!match) {
+ throw new Error(`Invalid AT URI: ${atUri}`)
+ }
+ return { did: match[1], rkey: match[2] }
+}
diff --git a/src/modules/atproto/publicNote.types.ts b/src/modules/atproto/publicNote.types.ts
new file mode 100644
index 0000000..07e4c0b
--- /dev/null
+++ b/src/modules/atproto/publicNote.types.ts
@@ -0,0 +1,29 @@
+export interface PublicNoteRecord {
+ uri: string
+ cid: string
+ value: PublicNote
+}
+
+export interface PublicNote {
+ $type: string
+ title: string
+ images: PublicNoteImage[]
+ content: string
+ createdAt: string
+ publishedAt: string
+ theme?: string
+ fontFamily?: string
+ fontSize?: string
+}
+
+export interface PublicNoteImage {
+ alt: string
+ image: PublicNoteBlob
+}
+
+export interface PublicNoteBlob {
+ $type: string
+ ref: { $link: string }
+ mimeType: string
+ size: number
+}
diff --git a/src/modules/atproto/withATProtoImages.ts b/src/modules/atproto/withATProtoImages.ts
new file mode 100644
index 0000000..3353482
--- /dev/null
+++ b/src/modules/atproto/withATProtoImages.ts
@@ -0,0 +1,13 @@
+export const withATProtoImages = (
+ markdown: string,
+ { endpoint, did }: { endpoint: string; did: string },
+): string => {
+ 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)
+ imageUrl.searchParams.set("cid", cid)
+ return `})`
+ })
+}
diff --git a/src/views/PublicNoteView.vue b/src/views/PublicNoteView.vue
index 6ba5f56..4a030b3 100644
--- a/src/views/PublicNoteView.vue
+++ b/src/views/PublicNoteView.vue
@@ -2,103 +2,70 @@
import { useATProtoLinks } from "@/hooks/useATProtoLinks.hook"
import { markdownBuilder } from "@/hooks/useMarkdown.hook"
import BackButton from "@/components/BackButton.vue"
+import StackedPublicNote from "@/components/StackedPublicNote.vue"
import { useRouteQueryStackedNotes } from "@/hooks/useRouteQueryStackedNotes.hook"
import { getUniqueAka } from "@/modules/atproto/getAka"
+import type { PublicNoteRecord } from "@/modules/atproto/publicNote.types"
+import { withATProtoImages } from "@/modules/atproto/withATProtoImages"
import { getUrl } from "@/modules/atproto/getUrl"
import { downloadFont } from "@/utils/downloadFont"
import { computedAsync } from "@vueuse/core"
import { computed, nextTick, watch } from "vue"
-
-export interface Root {
- uri: string
- cid: string
- value: Value
-}
-
-export interface Value {
- $type: string
- title: string
- images: Image[]
- content: string
- createdAt: string
- publishedAt: string
- theme?: string
- fontFamily?: string
- fontSize?: string
-}
-
-export interface Image {
- alt: string
- image: Image2
-}
-
-export interface Image2 {
- $type: string
- ref: Ref
- mimeType: string
- size: number
-}
-
-export interface Ref {
- $link: string
-}
+import { useResizeContainer } from "@/hooks/useResizeContainer.hook"
+import { publicNoteEventBus } from "@/bus/publicNoteEventBus"
+import { errorMessage } from "@/utils/notif"
const props = defineProps<{ did: string; rkey: string }>()
const did = computed(() => props.did)
const rkey = computed(() => props.rkey)
-const { scrollToFocusedNote } = useRouteQueryStackedNotes()
const author = computedAsync(async () => getUniqueAka(did.value))
const url = computedAsync(async () =>
getUrl({ did: did.value, rkey: rkey.value }),
)
-const article = computedAsync(async () =>
- url.value ? ((await fetch(url.value).then()).json() as Promise) : null,
+const noteRecord = computedAsync(async () =>
+ url.value
+ ? ((await fetch(url.value).then()).json() as Promise)
+ : null,
)
-watch(article, () => {
- if (article.value?.value.fontFamily) {
- downloadFont(article.value.value.fontFamily)
+watch(noteRecord, () => {
+ if (noteRecord.value?.value.fontFamily) {
+ downloadFont(noteRecord.value.value.fontFamily)
}
- if (article.value?.value.fontSize) {
+ if (noteRecord.value?.value.fontSize) {
const root = document.documentElement
- root.style.setProperty("--font-size", `${article.value.value.fontSize}pt`)
+ root.style.setProperty(
+ "--font-size",
+ `${noteRecord.value.value.fontSize}pt`,
+ )
}
})
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 `})`
- })
-}
-
-const title = computed(() => article.value?.value.title)
+const title = computed(() => noteRecord.value?.value.title)
const content = computed(() =>
- article.value?.value.content
- ? toHTML(withATProtoImages(article.value?.value.content))
+ noteRecord.value?.value.content && author.value
+ ? toHTML(
+ withATProtoImages(noteRecord.value.value.content, {
+ endpoint: author.value.endpoint,
+ did: did.value,
+ }),
+ )
: "",
)
const publishedAt = computed(() =>
- article.value?.value.publishedAt
- ? new Date(article.value?.value.publishedAt).toLocaleDateString()
+ noteRecord.value?.value.publishedAt
+ ? new Date(noteRecord.value?.value.publishedAt).toLocaleDateString()
: null,
)
+const { stackedNotes, scrollToFocusedNote } = useRouteQueryStackedNotes()
const { listenToClick } = useATProtoLinks("note-display")
+useResizeContainer("note-container", stackedNotes)
watch(
content,
@@ -111,7 +78,7 @@ watch(
-