Browse Source

Make node children lazy-load

master
buttercat1791 1 year ago
parent
commit
d723a56fe5
  1. 13
      src/lib/data_structures/lazy.ts
  2. 30
      src/lib/data_structures/publication_tree.ts

13
src/lib/data_structures/lazy.ts

@ -0,0 +1,13 @@
export class Lazy<T> {
#value?: T;
constructor(private readonly resolver: () => Promise<T>) {}
async value(): Promise<T> {
if (!this.#value) {
this.#value = await this.resolver();
}
return this.#value;
}
}

30
src/lib/data_structures/publication_tree.ts

@ -1,10 +1,11 @@
import type NDK from "@nostr-dev-kit/ndk"; import type NDK from "@nostr-dev-kit/ndk";
import type { NDKEvent, NDKFilter } from "@nostr-dev-kit/ndk"; import type { NDKEvent, NDKFilter } from "@nostr-dev-kit/ndk";
import type { Lazy } from "./lazy";
interface PublicationTreeNode { interface PublicationTreeNode {
address: string; address: string;
parent?: PublicationTreeNode; parent?: PublicationTreeNode;
children?: PublicationTreeNode[]; children?: Array<Lazy<PublicationTreeNode>>;
} }
export class PublicationTree implements AsyncIterable<NDKEvent> { export class PublicationTree implements AsyncIterable<NDKEvent> {
@ -40,7 +41,10 @@ export class PublicationTree implements AsyncIterable<NDKEvent> {
constructor(rootEvent: NDKEvent, ndk: NDK) { constructor(rootEvent: NDKEvent, ndk: NDK) {
const rootAddress = this.getAddressFromEvent(rootEvent); const rootAddress = this.getAddressFromEvent(rootEvent);
this.root = { address: rootAddress, children: [] }; this.root = {
address: rootAddress,
children: [],
};
this.nodes = new Map<string, PublicationTreeNode>(); this.nodes = new Map<string, PublicationTreeNode>();
this.nodes.set(rootAddress, this.root); this.nodes.set(rootAddress, this.root);
@ -70,11 +74,13 @@ export class PublicationTree implements AsyncIterable<NDKEvent> {
); );
} }
// TODO: Determine node type.
const node = { const node = {
address, address,
parent: parentNode, parent: parentNode,
children: [], children: [],
}; };
// TODO: Define a resolver for the lazy node.
parentNode.children!.push(node); parentNode.children!.push(node);
this.nodes.set(address, node); this.nodes.set(address, node);
this.events.set(address, event); this.events.set(address, event);
@ -223,13 +229,13 @@ export class PublicationTree implements AsyncIterable<NDKEvent> {
let nextSibling: PublicationTreeNode | null = null; let nextSibling: PublicationTreeNode | null = null;
do { do {
const siblings: PublicationTreeNode[] = parent!.children!; const siblings: Lazy<PublicationTreeNode>[] = parent!.children!;
const currentIndex = siblings.findIndex(sibling => sibling.address === currentNode!.address); const currentIndex = siblings.findIndex(async sibling => (await sibling.value()).address === currentNode!.address);
nextSibling = siblings.at(currentIndex + 1) ?? null; nextSibling = (await siblings.at(currentIndex + 1)?.value()) ?? null;
// If the next sibling has children, it is not a leaf. // If the next sibling has children, it is not a leaf.
if ((nextSibling?.children?.length ?? 0) > 0) { if ((nextSibling?.children?.length ?? 0) > 0) {
currentNode = nextSibling!.children!.at(0)!; currentNode = (await nextSibling!.children!.at(0)!.value())!;
parent = currentNode.parent; parent = currentNode.parent;
nextSibling = null; nextSibling = null;
} }
@ -266,7 +272,7 @@ export class PublicationTree implements AsyncIterable<NDKEvent> {
} }
} }
moveToFirstChild(): boolean { async moveToFirstChild(): Promise<boolean> {
if (!this.currentNode) { if (!this.currentNode) {
throw new Error("Cursor: Current node is null or undefined."); throw new Error("Cursor: Current node is null or undefined.");
} }
@ -282,22 +288,22 @@ export class PublicationTree implements AsyncIterable<NDKEvent> {
// TODO: Fetch any missing children, then return the first child. // TODO: Fetch any missing children, then return the first child.
} }
this.currentNode = this.currentNode.children?.at(0); this.currentNode = (await this.currentNode.children?.at(0)?.value())!;
return true; return true;
} }
moveToNextSibling(): boolean { async moveToNextSibling(): Promise<boolean> {
if (!this.currentNode) { if (!this.currentNode) {
throw new Error("Cursor: Current node is null or undefined."); throw new Error("Cursor: Current node is null or undefined.");
} }
const parent = this.currentNode.parent; const parent = this.currentNode.parent;
const siblings = parent?.children; const siblings = parent?.children;
const currentIndex = siblings?.findIndex(sibling => const currentIndex = siblings?.findIndex(async sibling =>
sibling.address === this.currentNode!.address (await sibling.value()).address === this.currentNode!.address
); );
const nextSibling = siblings?.at(currentIndex! + 1); const nextSibling = (await siblings?.at(currentIndex! + 1)?.value()) ?? null;
if (!nextSibling) { if (!nextSibling) {
return false; return false;
} }

Loading…
Cancel
Save