diff --git a/src/lib/components/publications/Publication.svelte b/src/lib/components/publications/Publication.svelte index f7e026f..7147de4 100644 --- a/src/lib/components/publications/Publication.svelte +++ b/src/lib/components/publications/Publication.svelte @@ -15,13 +15,13 @@ } from "flowbite-svelte-icons"; import type { NDKEvent } from "@nostr-dev-kit/ndk"; import PublicationSection from "./PublicationSection.svelte"; - import type { PublicationTree } from "$lib/data_structures/publication_tree"; import Details from "$components/util/Details.svelte"; import { publicationColumnVisibility } from "$lib/stores"; import BlogHeader from "$components/cards/BlogHeader.svelte"; import Interactions from "$components/util/Interactions.svelte"; import TocToggle from "$components/util/TocToggle.svelte"; import { pharosInstance } from '$lib/parser'; + import type { SveltePublicationTree } from "./svelte_publication_tree.svelte"; let { rootAddress, publicationType, indexEvent } = $props<{ rootAddress: string; @@ -29,7 +29,7 @@ indexEvent: NDKEvent; }>(); - const publicationTree = getContext("publicationTree") as PublicationTree; + const publicationTree = getContext("publicationTree") as SveltePublicationTree; // #region Loading diff --git a/src/lib/components/publications/PublicationSection.svelte b/src/lib/components/publications/PublicationSection.svelte index 6c2586a..7b24fb3 100644 --- a/src/lib/components/publications/PublicationSection.svelte +++ b/src/lib/components/publications/PublicationSection.svelte @@ -6,7 +6,8 @@ import { getContext } from "svelte"; import type { Asciidoctor, Document } from "asciidoctor"; import { getMatchingTags } from '$lib/utils/nostrUtils'; - + import type { SveltePublicationTree } from "./svelte_publication_tree.svelte"; + let { address, rootAddress, @@ -19,7 +20,7 @@ ref: (ref: HTMLElement) => void, } = $props(); - const publicationTree: PublicationTree = getContext('publicationTree'); + const publicationTree: SveltePublicationTree = getContext('publicationTree'); const asciidoctor: Asciidoctor = getContext('asciidoctor'); let leafEvent: Promise = $derived.by(async () => diff --git a/src/lib/components/publications/svelte_publication_tree.svelte.ts b/src/lib/components/publications/svelte_publication_tree.svelte.ts new file mode 100644 index 0000000..cd96118 --- /dev/null +++ b/src/lib/components/publications/svelte_publication_tree.svelte.ts @@ -0,0 +1,56 @@ +import { SvelteSet } from "svelte/reactivity"; +import { PublicationTree } from "../../data_structures/publication_tree.ts"; +import { NDKEvent } from "../../utils/nostrUtils.ts"; +import NDK from "@nostr-dev-kit/ndk"; + +export class SveltePublicationTree { + resolvedAddresses: SvelteSet = new SvelteSet(); + + #publicationTree: PublicationTree; + + constructor(rootEvent: NDKEvent, ndk: NDK) { + this.#publicationTree = new PublicationTree(rootEvent, ndk); + + this.#publicationTree.onNodeResolved(this.#handleNodeResolved); + } + + // #region Proxied Public Methods + + getEvent(address: string): Promise { + return this.#publicationTree.getEvent(address); + } + + getHierarchy(address: string): Promise { + return this.#publicationTree.getHierarchy(address); + } + + setBookmark(address: string) { + this.#publicationTree.setBookmark(address); + } + + // #endregion + + // #region Proxied Async Iterator Methods + + [Symbol.asyncIterator](): AsyncIterator { + return this; + } + + next(): Promise> { + return this.#publicationTree.next(); + } + + previous(): Promise> { + return this.#publicationTree.previous(); + } + + // #endregion + + // #region Private Methods + + #handleNodeResolved(address: string) { + this.resolvedAddresses.add(address); + } + + // #endregion +} \ No newline at end of file diff --git a/src/lib/data_structures/publication_tree.ts b/src/lib/data_structures/publication_tree.ts index 3184b29..7f4c677 100644 --- a/src/lib/data_structures/publication_tree.ts +++ b/src/lib/data_structures/publication_tree.ts @@ -22,14 +22,6 @@ interface PublicationTreeNode { } export class PublicationTree implements AsyncIterable { - // TODO: Abstract this into a `SveltePublicationTree` wrapper class. - /** - * A reactive set of addresses of the events that have been resolved (loaded) into the tree. - * Svelte components can use this set in reactive code blocks to trigger updates when new nodes - * are added to the tree. - */ - resolvedAddresses: SvelteSet = new SvelteSet(); - /** * The root node of the tree. */ @@ -524,7 +516,6 @@ export class PublicationTree implements AsyncIterable { } this.#events.set(address, event); - this.resolvedAddresses.add(address); const childAddresses = event.tags.filter(tag => tag[0] === 'a').map(tag => tag[1]); diff --git a/src/routes/publication/+page.svelte b/src/routes/publication/+page.svelte index 9316069..7defecf 100644 --- a/src/routes/publication/+page.svelte +++ b/src/routes/publication/+page.svelte @@ -3,13 +3,12 @@ import { TextPlaceholder } from "flowbite-svelte"; import type { PageProps } from "./$types"; import { onDestroy, setContext } from "svelte"; - import { PublicationTree } from "$lib/data_structures/publication_tree"; import Processor from "asciidoctor"; import ArticleNav from "$components/util/ArticleNav.svelte"; - + import { SveltePublicationTree } from "$lib/components/publications/svelte_publication_tree.svelte"; let { data }: PageProps = $props(); - const publicationTree = new PublicationTree(data.indexEvent, data.ndk); + const publicationTree = new SveltePublicationTree(data.indexEvent, data.ndk); setContext("publicationTree", publicationTree); setContext("asciidoctor", Processor());