From 9e35d582050edc076ba8c7f91337de84e38b02eb Mon Sep 17 00:00:00 2001 From: buttercat1791 Date: Wed, 9 Apr 2025 09:08:15 -0500 Subject: [PATCH 01/16] Update heading snippet for commonality with Preview component --- src/lib/snippets/PublicationSnippets.svelte | 31 ++++----------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/src/lib/snippets/PublicationSnippets.svelte b/src/lib/snippets/PublicationSnippets.svelte index 26645fa..8f9e0cc 100644 --- a/src/lib/snippets/PublicationSnippets.svelte +++ b/src/lib/snippets/PublicationSnippets.svelte @@ -5,31 +5,12 @@ {#snippet sectionHeading(title: string, depth: number)} - {#if depth === 0} -

- {title} -

- {:else if depth === 1} -

- {title} -

- {:else if depth === 2} -

- {title} -

- {:else if depth === 3} -

- {title} -

- {:else if depth === 4} -
- {title} -
- {:else} -
- {title} -
- {/if} + {@const headingLevel = Math.min(depth + 1, 6)} + + + + {title} + {/snippet} {#snippet contentParagraph(content: string, publicationType: string, isSectionStart: boolean)} From 5486c7368576acfb57d6c45b1b27ee8c4c8aff6a Mon Sep 17 00:00:00 2001 From: buttercat1791 Date: Wed, 9 Apr 2025 09:16:41 -0500 Subject: [PATCH 02/16] Instanatiate PublicationTree and make it available to components --- src/app.d.ts | 5 +++++ src/routes/publication/+page.svelte | 7 ++++++- src/routes/publication/+page.ts | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/app.d.ts b/src/app.d.ts index 731967b..418205d 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -1,4 +1,8 @@ // See https://kit.svelte.dev/docs/types#app + +import NDK, { NDKEvent } from "@nostr-dev-kit/ndk"; +import Pharos from "./lib/parser.ts"; + // for information about these interfaces declare global { namespace App { @@ -9,6 +13,7 @@ declare global { parser?: Pharos; waitable?: Promise; publicationType?: string; + publicationRootEvent?: NDKEvent; } // interface Platform {} } diff --git a/src/routes/publication/+page.svelte b/src/routes/publication/+page.svelte index dbd673f..b566965 100644 --- a/src/routes/publication/+page.svelte +++ b/src/routes/publication/+page.svelte @@ -2,10 +2,15 @@ import Article from "$lib/components/Publication.svelte"; import { TextPlaceholder } from "flowbite-svelte"; import type { PageData } from "./$types"; - import { onDestroy } from "svelte"; + import { onDestroy, setContext } from "svelte"; + import { PublicationTree } from "$lib/data_structures/publication_tree"; let { data }: { data: PageData } = $props(); + const publicationTree = new PublicationTree(data.publicationRootEvent, data.ndk); + + setContext('publicationTree', publicationTree); + onDestroy(() => data.parser.reset()); diff --git a/src/routes/publication/+page.ts b/src/routes/publication/+page.ts index 286063a..72116ec 100644 --- a/src/routes/publication/+page.ts +++ b/src/routes/publication/+page.ts @@ -102,5 +102,6 @@ export const load: PageLoad = async ({ url, parent }: { url: URL; parent: () => return { waitable: fetchPromise, publicationType, + publicationRootEvent: indexEvent, }; }; From 5229e807c714c979bbfa307a4b5ffa89917d3fa4 Mon Sep 17 00:00:00 2001 From: buttercat1791 Date: Mon, 14 Apr 2025 08:57:50 -0500 Subject: [PATCH 03/16] Require SvelteKit >= 2.16.0 --- deno.lock | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deno.lock b/deno.lock index f113237..9438da1 100644 --- a/deno.lock +++ b/deno.lock @@ -2887,7 +2887,7 @@ "npm:@sveltejs/adapter-auto@3", "npm:@sveltejs/adapter-node@^5.2.12", "npm:@sveltejs/adapter-static@3", - "npm:@sveltejs/kit@2", + "npm:@sveltejs/kit@^2.16.0", "npm:@sveltejs/vite-plugin-svelte@4", "npm:@tailwindcss/forms@0.5", "npm:@tailwindcss/typography@0.5", diff --git a/package.json b/package.json index 2323efa..ca9cd67 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "@sveltejs/adapter-auto": "3.x", "@sveltejs/adapter-node": "^5.2.12", "@sveltejs/adapter-static": "3.x", - "@sveltejs/kit": "2.x", + "@sveltejs/kit": "^2.16.0", "@sveltejs/vite-plugin-svelte": "4.x", "@types/he": "1.2.x", "@types/node": "22.x", From c63360d1f0b8b43decf23197c6d26dbd9c70b5f6 Mon Sep 17 00:00:00 2001 From: buttercat1791 Date: Mon, 14 Apr 2025 09:05:56 -0500 Subject: [PATCH 04/16] Update publication page load data handling --- src/app.d.ts | 3 ++- src/routes/publication/+page.svelte | 17 ++++------------- src/routes/publication/+page.ts | 3 ++- 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/app.d.ts b/src/app.d.ts index 418205d..10e50ba 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -13,7 +13,8 @@ declare global { parser?: Pharos; waitable?: Promise; publicationType?: string; - publicationRootEvent?: NDKEvent; + indexEvent?: NDKEvent; + url?: URL; } // interface Platform {} } diff --git a/src/routes/publication/+page.svelte b/src/routes/publication/+page.svelte index e6f532d..032b2f3 100644 --- a/src/routes/publication/+page.svelte +++ b/src/routes/publication/+page.svelte @@ -1,28 +1,19 @@ + + +
+ {#await Promise.all([sectionEvent, publicationType])} + + {:then [sectionEvent, publicationType]} + + {@render contentParagraph(sectionEvent?.content ?? '', publicationType ?? 'article', false)} + {/await} +
+ From 46f61da01dbcae8dc51630246dc0332798c02035 Mon Sep 17 00:00:00 2001 From: buttercat1791 Date: Mon, 14 Apr 2025 23:11:57 -0500 Subject: [PATCH 07/16] Begin to implement import on visibility for publication content --- src/lib/components/Publication.svelte | 82 ++++++++++++++++---- src/lib/components/PublicationSection.svelte | 22 +++++- src/routes/publication/+page.svelte | 6 +- 3 files changed, 92 insertions(+), 18 deletions(-) diff --git a/src/lib/components/Publication.svelte b/src/lib/components/Publication.svelte index 4ff9c7c..167cf67 100644 --- a/src/lib/components/Publication.svelte +++ b/src/lib/components/Publication.svelte @@ -9,25 +9,64 @@ TextPlaceholder, Tooltip, } from "flowbite-svelte"; - import { onMount } from "svelte"; + import { getContext, onMount } from "svelte"; import { BookOutline } from "flowbite-svelte-icons"; - import Preview from "./Preview.svelte"; - import { pharosInstance } from "$lib/parser"; import { page } from "$app/state"; - import { ndkInstance } from "$lib/ndk"; import type { NDKEvent } from "@nostr-dev-kit/ndk"; import PublicationSection from "./PublicationSection.svelte"; + import type { PublicationTree } from "$lib/data_structures/publication_tree"; - let { rootId, publicationType, indexEvent } = $props<{ - rootId: string, + let { rootAddress, publicationType, indexEvent } = $props<{ + rootAddress: string, publicationType: string, indexEvent: NDKEvent }>(); - if (rootId !== $pharosInstance.getRootIndexId()) { - console.error("Root ID does not match parser root index ID"); + const publicationTree = getContext('publicationTree') as PublicationTree; + + // #region Loading + + // TODO: Test load handling. + + let leaves = $state([]); + let isLoading = $state(false); + let lastElementRef = $state(null); + + let observer: IntersectionObserver; + + async function loadMore(count: number) { + isLoading = true; + + for (let i = 0; i < count; i++) { + const nextItem = await publicationTree.next(); + if (nextItem.done) { + break; + } + leaves.push(nextItem.value); + } + + isLoading = false; + } + + function setLastElementRef(el: HTMLElement, i: number) { + if (i === leaves.length - 1) { + lastElementRef = el; + } } + $effect(() => { + if (!lastElementRef) { + return; + } + + observer.observe(lastElementRef!); + return () => observer.unobserve(lastElementRef!); + }); + + // #endregion + + // #region ToC + const tocBreakpoint = 1140; let activeHash = $state(page.url.hash); @@ -82,21 +121,33 @@ } } + // #endregion + onMount(() => { // Always check whether the TOC sidebar should be visible. setTocVisibilityOnResize(); - window.addEventListener("hashchange", scrollToElementWithOffset); // Also handle the case where the user lands on the page with a hash in the URL scrollToElementWithOffset(); - window.addEventListener("resize", setTocVisibilityOnResize); window.addEventListener("click", hideTocOnClick); + // Set up the intersection observer. + observer = new IntersectionObserver((entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting && !isLoading) { + loadMore(8); + } + }); + }, { threshold: 0.5 }); + loadMore(16); + return () => { window.removeEventListener("hashchange", scrollToElementWithOffset); window.removeEventListener("resize", setTocVisibilityOnResize); window.removeEventListener("click", hideTocOnClick); + + observer.disconnect(); }; }); @@ -115,7 +166,7 @@ Show Table of Contents {/if} - +
- - + {#each leaves as leaf, i} + setLastElementRef(el, i)} + /> + {/each}