Browse Source

Create Svelte-specific wrapper that proxies `PublicationTree`

The wrapper keeps the core implementation framework-agnostic, but lets us build Svelte's reactivity into the wrapper.
master
buttercat1791 10 months ago
parent
commit
c6effb3839
  1. 4
      src/lib/components/publications/Publication.svelte
  2. 5
      src/lib/components/publications/PublicationSection.svelte
  3. 56
      src/lib/components/publications/svelte_publication_tree.svelte.ts
  4. 9
      src/lib/data_structures/publication_tree.ts
  5. 5
      src/routes/publication/+page.svelte

4
src/lib/components/publications/Publication.svelte

@ -15,13 +15,13 @@ @@ -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 @@ @@ -29,7 +29,7 @@
indexEvent: NDKEvent;
}>();
const publicationTree = getContext("publicationTree") as PublicationTree;
const publicationTree = getContext("publicationTree") as SveltePublicationTree;
// #region Loading

5
src/lib/components/publications/PublicationSection.svelte

@ -6,7 +6,8 @@ @@ -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 @@ @@ -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<NDKEvent | null> = $derived.by(async () =>

56
src/lib/components/publications/svelte_publication_tree.svelte.ts

@ -0,0 +1,56 @@ @@ -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<string> = 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<NDKEvent | null> {
return this.#publicationTree.getEvent(address);
}
getHierarchy(address: string): Promise<NDKEvent[]> {
return this.#publicationTree.getHierarchy(address);
}
setBookmark(address: string) {
this.#publicationTree.setBookmark(address);
}
// #endregion
// #region Proxied Async Iterator Methods
[Symbol.asyncIterator](): AsyncIterator<NDKEvent | null> {
return this;
}
next(): Promise<IteratorResult<NDKEvent | null>> {
return this.#publicationTree.next();
}
previous(): Promise<IteratorResult<NDKEvent | null>> {
return this.#publicationTree.previous();
}
// #endregion
// #region Private Methods
#handleNodeResolved(address: string) {
this.resolvedAddresses.add(address);
}
// #endregion
}

9
src/lib/data_structures/publication_tree.ts

@ -22,14 +22,6 @@ interface PublicationTreeNode { @@ -22,14 +22,6 @@ interface PublicationTreeNode {
}
export class PublicationTree implements AsyncIterable<NDKEvent | null> {
// 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<string> = new SvelteSet();
/**
* The root node of the tree.
*/
@ -524,7 +516,6 @@ export class PublicationTree implements AsyncIterable<NDKEvent | null> { @@ -524,7 +516,6 @@ export class PublicationTree implements AsyncIterable<NDKEvent | null> {
}
this.#events.set(address, event);
this.resolvedAddresses.add(address);
const childAddresses = event.tags.filter(tag => tag[0] === 'a').map(tag => tag[1]);

5
src/routes/publication/+page.svelte

@ -3,13 +3,12 @@ @@ -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());

Loading…
Cancel
Save