From 6d7f4217eec11e0cf29d0dde7190665ae92d7502 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nu=C5=A1a=20Puk=C5=A1i=C4=8D?= Date: Thu, 1 May 2025 16:01:22 +0200 Subject: [PATCH 01/21] Intermediate state where publications have 'covers' and columns are still all messed up --- src/app.css | 14 ++++- src/lib/components/Preview.svelte | 21 +++---- src/lib/components/Publication.svelte | 17 +++--- src/lib/components/blog/BlogHeader.svelte | 65 ++++++++++++++++++++ src/lib/components/util/ArticleNav.svelte | 74 +++++++++++++++-------- src/lib/components/util/Details.svelte | 6 +- src/routes/publication/+page.svelte | 4 +- 7 files changed, 149 insertions(+), 52 deletions(-) create mode 100644 src/lib/components/blog/BlogHeader.svelte diff --git a/src/app.css b/src/app.css index 8fea2b5..f7e32e3 100644 --- a/src/app.css +++ b/src/app.css @@ -55,11 +55,12 @@ /* Content */ main { - @apply max-w-full flex; + @apply max-w-full flex mb-2; } - main.blog { - max-height: calc(100vh - 130px); + /* To scroll columns independently */ + main.publication { + /* max-height: calc(100vh - 130px); */ } main.main-leather, @@ -219,3 +220,10 @@ @apply bg-primary-0 dark:bg-primary-1000 text-gray-800 dark:text-gray-300; } } + +.line-ellipsis { + max-width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} \ No newline at end of file diff --git a/src/lib/components/Preview.svelte b/src/lib/components/Preview.svelte index 093a640..b2ec5f4 100644 --- a/src/lib/components/Preview.svelte +++ b/src/lib/components/Preview.svelte @@ -4,6 +4,7 @@ import { CaretDownSolid, CaretUpSolid, EditOutline } from 'flowbite-svelte-icons'; import Self from './Preview.svelte'; import { contentParagraph, sectionHeading } from '$lib/snippets/PublicationSnippets.svelte'; + import BlogHeader from "./blog/BlogHeader.svelte"; // TODO: Fix move between parents. @@ -93,6 +94,10 @@ } }); + function getBlogEvent(index: number) { + return blogEntries[index][1]; + } + function byline(rootId: string, index: number) { console.log(rootId, index, blogEntries); const event = blogEntries[index][1]; @@ -198,7 +203,7 @@ {#snippet sectionHeading(title: string, depth: number)} {@const headingLevel = Math.min(depth + 1, 6)} {@const className = $pharosInstance.isFloatingTitle(rootId) ? 'discrete' : 'h-leather'} - + {title} @@ -221,12 +226,6 @@

{/snippet} -{#snippet readMoreLink(rootId: string, index: number)} -

- -

-{/snippet} - {#snippet contentParagraph(content: string, publicationType: string)} {#if publicationType === 'novel'}

@@ -294,17 +293,13 @@ {:else} - {#if publicationType === 'blog' && depth === 1} - {@render coverImage(rootId, index, depth)} - {@render sectionHeading(title!, depth)} - {@render blogMetadata(rootId, index)} - {:else} + {#if !(publicationType === 'blog' && depth === 1)} {@render sectionHeading(title!, depth)} {/if} {/if} {#if publicationType === 'blog' && depth === 1} - {@render readMoreLink(rootId, index)} + {:else } {#key subtreeUpdateCount} {#each orderedChildren as id, index} diff --git a/src/lib/components/Publication.svelte b/src/lib/components/Publication.svelte index e917ff1..8d62ac5 100644 --- a/src/lib/components/Publication.svelte +++ b/src/lib/components/Publication.svelte @@ -1,8 +1,6 @@ {#if $publicationColumnVisibility.details} -

-
+
+
+
+
{/if} @@ -50,6 +49,10 @@ {publicationType === 'blog' ? 'max-w-xl flex-grow-1' : 'max-w-2xl flex-grow-2' } {currentBlog !== null ? 'discreet' : ''} "> +
+
+
+
{/if} @@ -63,8 +66,8 @@ {/if} {#if $publicationColumnVisibility.social } -
-

Social column

+
+
{/if} diff --git a/src/lib/components/blog/BlogHeader.svelte b/src/lib/components/blog/BlogHeader.svelte new file mode 100644 index 0000000..276b206 --- /dev/null +++ b/src/lib/components/blog/BlogHeader.svelte @@ -0,0 +1,65 @@ + + +{#if title != null} + +
+
+ + {publishedAt()} +
+ {#if image} +
+ +
+ {/if} +
+ + +
+
+
+
{likeCount}
+
{likeCount}
+
{likeCount}
+
{likeCount}
+
{likeCount}
+ +
+
+
+
+{/if} diff --git a/src/lib/components/util/ArticleNav.svelte b/src/lib/components/util/ArticleNav.svelte index 5049c7e..f810d39 100644 --- a/src/lib/components/util/ArticleNav.svelte +++ b/src/lib/components/util/ArticleNav.svelte @@ -1,24 +1,42 @@ -
\ No newline at end of file diff --git a/src/lib/components/util/Details.svelte b/src/lib/components/util/Details.svelte index df12ee6..a1b4bb2 100644 --- a/src/lib/components/util/Details.svelte +++ b/src/lib/components/util/Details.svelte @@ -37,18 +37,18 @@ {#if summary} -
+

{summary}

{/if} -
+

Index author:

{#if source !== null} -
Source: {source}
+
Source: {source}
{/if} {#if type !== null}
Publication type: {type}
diff --git a/src/routes/publication/+page.svelte b/src/routes/publication/+page.svelte index 697ca4e..486a655 100644 --- a/src/routes/publication/+page.svelte +++ b/src/routes/publication/+page.svelte @@ -51,10 +51,10 @@ {#key data} - + {/key} -
+
{#await data.waitable} {:then} From e922f112cfbc203ea5d3369ae3b16982d288c8b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nu=C5=A1a=20Puk=C5=A1i=C4=8D?= Date: Thu, 1 May 2025 18:19:52 +0200 Subject: [PATCH 02/21] Merge ate some code... now it's back --- src/lib/components/Publication.svelte | 78 +-------------------------- 1 file changed, 1 insertion(+), 77 deletions(-) diff --git a/src/lib/components/Publication.svelte b/src/lib/components/Publication.svelte index a9ec1ee..369bec3 100644 --- a/src/lib/components/Publication.svelte +++ b/src/lib/components/Publication.svelte @@ -10,8 +10,6 @@ Tooltip, } from "flowbite-svelte"; import { getContext, onMount } from "svelte"; - import { BookOutline } from "flowbite-svelte-icons"; - import { page } from "$app/state"; import type { NDKEvent } from "@nostr-dev-kit/ndk"; import PublicationSection from "./PublicationSection.svelte"; import type { PublicationTree } from "$lib/data_structures/publication_tree"; @@ -107,41 +105,9 @@ } } - /** - * Hides the table of contents sidebar when the window shrinks below a certain size. This - * prevents the sidebar from occluding the article content. - */ - function setTocVisibilityOnResize() { - showToc = window.innerWidth >= tocBreakpoint; - showTocButton = window.innerWidth < tocBreakpoint; - } - - /** - * Hides the table of contents sidebar when the user clicks outside of it. - */ - function hideTocOnClick(ev: MouseEvent) { - const target = ev.target as HTMLElement; - - if (target.closest(".sidebar-leather") || target.closest(".btn-leather")) { - return; - } - - if (showToc) { - showToc = false; - } - } - // #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) => { @@ -153,13 +119,10 @@ loadMore(8); return () => { - window.removeEventListener("hashchange", scrollToElementWithOffset); - window.removeEventListener("resize", setTocVisibilityOnResize); - window.removeEventListener("click", hideTocOnClick); - observer.disconnect(); }; }); + {#if $publicationColumnVisibility.details} @@ -170,37 +133,6 @@
{/if} - -{#if showTocButton && !showToc} - -{/if} - - - {#if isDefaultVisible()}
-
{#each leaves as leaf, i} {/each}
-
{/if} {#if currentBlog !== null && $publicationColumnVisibility.inner } @@ -235,9 +165,3 @@
{/if} - - From 05755293e83ba37fa154ae1160c1f3b700a0b527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nu=C5=A1a=20Puk=C5=A1i=C4=8D?= Date: Thu, 1 May 2025 18:20:18 +0200 Subject: [PATCH 03/21] Check if tags exist --- src/lib/parser.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/parser.ts b/src/lib/parser.ts index 72bb2d4..812967a 100644 --- a/src/lib/parser.ts +++ b/src/lib/parser.ts @@ -649,7 +649,7 @@ export default class Pharos { ); // if a blog, save complete events for later - if (event.getMatchingTags("type")[0][1] === 'blog') { + if (event.getMatchingTags("type").length > 0 && event.getMatchingTags("type")[0][1] === 'blog') { childEvents.forEach(child => { if (child) { this.blogEntries.set(child?.getMatchingTags("d")?.[0]?.[1], child); @@ -661,7 +661,7 @@ export default class Pharos { if (event.created_at) { this.rootIndexMetadata.publicationDate = new Date(event.created_at * 1000).toDateString(); } - if (event.getMatchingTags('image')) { + if (event.getMatchingTags('image').length > 0) { this.rootIndexMetadata.coverImage = event.getMatchingTags('image')[0][1]; } From 3605eb295b25b8095d7a561b51152d371e5c8ec2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nu=C5=A1a=20Puk=C5=A1i=C4=8D?= Date: Sun, 4 May 2025 12:38:49 +0200 Subject: [PATCH 04/21] Display height was off, innerHeight overestimates the viewport --- src/routes/+layout.svelte | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index b7593c3..8e1a965 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -6,9 +6,6 @@ import { Alert } from "flowbite-svelte"; import { HammerSolid } from "flowbite-svelte-icons"; - // Compute viewport height. - $: displayHeight = window.innerHeight; - // Get standard metadata for OpenGraph tags let title = 'Library of Alexandria'; let currentUrl = $page.url.href; @@ -18,7 +15,8 @@ let summary = 'Alexandria is a digital library, utilizing Nostr events for curated publications and wiki pages.'; onMount(() => { - document.body.style.height = `${displayHeight}px`; + const rect = document.body.getBoundingClientRect(); + document.body.style.height = `${rect.height}px`; }); @@ -44,7 +42,7 @@
- + Pardon our dust! The publication view is currently using an experimental loader, and may be unstable. From 86976c5bf81df4dcc6ae21d5ba65895883d36e8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nu=C5=A1a=20Puk=C5=A1i=C4=8D?= Date: Sun, 4 May 2025 12:39:49 +0200 Subject: [PATCH 05/21] Update ArticleNav --- src/lib/components/util/ArticleNav.svelte | 61 ++++++++--------------- src/routes/publication/+page.svelte | 6 +-- 2 files changed, 23 insertions(+), 44 deletions(-) diff --git a/src/lib/components/util/ArticleNav.svelte b/src/lib/components/util/ArticleNav.svelte index f810d39..8df36bf 100644 --- a/src/lib/components/util/ArticleNav.svelte +++ b/src/lib/components/util/ArticleNav.svelte @@ -5,24 +5,6 @@ import { publicationColumnVisibility } from "$lib/stores"; import InlineProfile from "$components/util/InlineProfile.svelte"; import type { NDKEvent } from "@nostr-dev-kit/ndk"; - import { onMount } from 'svelte'; - import { fade } from 'svelte/transition'; - - let scrollY = $state(0); - - // Run this every time the scroll event happens - function updateScroll() { - scrollY = window.scrollY; - } - - onMount(() => { - window.addEventListener('scroll', updateScroll); - updateScroll(); // Set initial value - - return () => { - window.removeEventListener('scroll', updateScroll); - }; - }); let { rootId, @@ -51,31 +33,28 @@ - \ No newline at end of file diff --git a/src/routes/publication/+page.svelte b/src/routes/publication/+page.svelte index f0695e2..ac297c4 100644 --- a/src/routes/publication/+page.svelte +++ b/src/routes/publication/+page.svelte @@ -46,14 +46,14 @@ -{#key data} - -{/key}
{#await data.waitable} {:then} + {#key data} + + {/key} Date: Sun, 4 May 2025 12:41:12 +0200 Subject: [PATCH 06/21] Blog contents with placeholder interactions --- src/app.css | 21 ++++-- src/lib/components/Publication.svelte | 79 ++++++++++++--------- src/lib/components/blog/BlogHeader.svelte | 42 ++++++----- src/lib/components/util/CardActions.svelte | 3 +- src/lib/components/util/Interactions.svelte | 62 ++++++++++++++++ src/lib/components/util/ZapOutline.svelte | 19 +++++ src/styles/publications.css | 38 +++++----- src/styles/scrollbar.css | 3 +- 8 files changed, 183 insertions(+), 84 deletions(-) create mode 100644 src/lib/components/util/Interactions.svelte create mode 100644 src/lib/components/util/ZapOutline.svelte diff --git a/src/app.css b/src/app.css index c730a8d..05539ad 100644 --- a/src/app.css +++ b/src/app.css @@ -55,13 +55,15 @@ /* Content */ main { - @apply max-w-full flex mb-2; + @apply max-w-full flex; } /* To scroll columns independently */ - main.publication { - /* max-height: calc(100vh - 130px); */ - } + main.publication.blog { + display: flex; + flex-direction: column; + max-height: calc(100vh - 76px); + } main.main-leather, article.article-leather { @@ -247,6 +249,17 @@ .link { @apply underline cursor-pointer hover:text-primary-400 dark:hover:text-primary-500; } + + /* Card with transition */ + .ArticleBox.grid .ArticleBoxImage { + @apply max-h-0; + transition: max-height 0.5s ease; + } + + .ArticleBox.grid.active .ArticleBoxImage { + @apply max-h-72; + } + } @layer components { diff --git a/src/lib/components/Publication.svelte b/src/lib/components/Publication.svelte index 369bec3..e1555cd 100644 --- a/src/lib/components/Publication.svelte +++ b/src/lib/components/Publication.svelte @@ -9,12 +9,14 @@ TextPlaceholder, Tooltip, } from "flowbite-svelte"; + import { CaretLeftOutline } from 'flowbite-svelte-icons'; import { getContext, onMount } from "svelte"; 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/blog/BlogHeader.svelte"; let { rootAddress, publicationType, indexEvent } = $props<{ rootAddress: string, @@ -83,30 +85,15 @@ } $publicationColumnVisibility.inner = true; currentBlog = rootId; + // set current blog values for publication render + console.log(currentBlog); } - // #region ToC - - - function scrollToElementWithOffset() { - const hash = window.location.hash; - if (hash) { - const targetElement = document.querySelector(hash); - if (targetElement) { - const headerOffset = 80; - const elementPosition = targetElement.getBoundingClientRect().top; - const offsetPosition = elementPosition + window.scrollY - headerOffset; - - window.scrollTo({ - top: offsetPosition, - behavior: "auto", - }); - } - } + function backToMain() { + $publicationColumnVisibility.blog = true; + $publicationColumnVisibility.inner = false; } - // #endregion - onMount(() => { // Set up the intersection observer. observer = new IntersectionObserver((entries) => { @@ -134,28 +121,54 @@ {/if} {#if isDefaultVisible()} -
-
+
- {#each leaves as leaf, i} - setLastElementRef(el, i)} - /> - {/each} + + {#if publicationType === 'blog'} + + {#each leaves as leaf, i} + + {/each} + {:else} + {#each leaves as leaf, i} + setLastElementRef(el, i)} + /> + {/each} + {/if} +
{/if} {#if currentBlog !== null && $publicationColumnVisibility.inner } {#key currentBlog } -
- Todo... +
+
+ +
+ {#each leaves as leaf, i} + {#if leaf.tagAddress() === currentBlog} + setLastElementRef(el, i)} + /> + {/if} + {/each}
{/key} {/if} diff --git a/src/lib/components/blog/BlogHeader.svelte b/src/lib/components/blog/BlogHeader.svelte index 276b206..bfe5b6a 100644 --- a/src/lib/components/blog/BlogHeader.svelte +++ b/src/lib/components/blog/BlogHeader.svelte @@ -1,19 +1,18 @@ {#if title != null} - -
+ +
{publishedAt()}
- {#if image} -
- -
+ {#if image && active} +
+ +
{/if}
- + {#if active} + + {/if}
-
-
-
{likeCount}
-
{likeCount}
-
{likeCount}
-
{likeCount}
-
{likeCount}
- + {#if active} +
+
-
+ {/if}
{/if} diff --git a/src/lib/components/util/CardActions.svelte b/src/lib/components/util/CardActions.svelte index 177c8ee..c0d62d2 100644 --- a/src/lib/components/util/CardActions.svelte +++ b/src/lib/components/util/CardActions.svelte @@ -10,8 +10,7 @@ import { Button, Modal, Popover } from "flowbite-svelte"; import { standardRelays } from "$lib/consts"; import { neventEncode, naddrEncode } from "$lib/utils"; - import InlineProfile from "$components/util/InlineProfile.svelte"; - import Details from "./Details.svelte"; + import Details from "./Details.svelte"; let { event } = $props(); diff --git a/src/lib/components/util/Interactions.svelte b/src/lib/components/util/Interactions.svelte new file mode 100644 index 0000000..4263f05 --- /dev/null +++ b/src/lib/components/util/Interactions.svelte @@ -0,0 +1,62 @@ + + +
+
{likeCount}
+
{zapCount}
+
{highlightCount}
+
{commentCount}
+
\ No newline at end of file diff --git a/src/lib/components/util/ZapOutline.svelte b/src/lib/components/util/ZapOutline.svelte new file mode 100644 index 0000000..b5588c0 --- /dev/null +++ b/src/lib/components/util/ZapOutline.svelte @@ -0,0 +1,19 @@ + + + + + diff --git a/src/styles/publications.css b/src/styles/publications.css index 79cb2da..5616bd0 100644 --- a/src/styles/publications.css +++ b/src/styles/publications.css @@ -1,55 +1,55 @@ @layer components { /* AsciiDoc content */ - .note-leather p a { + .publication-leather p a { @apply underline hover:text-primary-500 dark:hover:text-primary-400; } - .note-leather section p { + .publication-leather section p { @apply w-full; } - .note-leather section p table { + .publication-leather section p table { @apply w-full table-fixed space-x-2 space-y-2; } - .note-leather section p table td { + .publication-leather section p table td { @apply p-2; } - .note-leather section p table td .content:has(> .imageblock) { + .publication-leather section p table td .content:has(> .imageblock) { @apply flex flex-col items-center; } - .note-leather .imageblock { + .publication-leather .imageblock { @apply flex flex-col space-y-2; } - .note-leather .imageblock .content { + .publication-leather .imageblock .content { @apply flex justify-center; } - .note-leather .imageblock .title { + .publication-leather .imageblock .title { @apply text-center; } - .note-leather .imageblock.left .content { + .publication-leather .imageblock.left .content { @apply justify-start; } - .note-leather .imageblock.left .title { + .publication-leather .imageblock.left .title { @apply text-left; } - .note-leather .imageblock.right .content { + .publication-leather .imageblock.right .content { @apply justify-end; } - .note-leather .imageblock.right .title { + .publication-leather .imageblock.right .title { @apply text-right; } - .note-leather section p table td .literalblock { + .publication-leather section p table td .literalblock { @apply my-2 p-2 border rounded border-gray-400 dark:border-gray-600; } - .note-leather .literalblock pre { + .publication-leather .literalblock pre { @apply p-3 text-wrap break-words; } @@ -58,7 +58,7 @@ } /* lists */ - .note-leather .ulist ul { + .publication-leather .ulist ul { @apply space-y-1 list-disc list-inside; } @@ -253,12 +253,8 @@ /** blog */ @screen lg { @media (hover: hover) { - .blog .discreet:not(:hover) .coverImage img { - @apply filter grayscale sepia brightness-75 opacity-50 transition duration-500 ease-in-out saturate-200 hue-rotate-20; - } - - .blog .discreet:not(:hover) .h-leather { - @apply filter grayscale sepia brightness-75 opacity-50 transition duration-500 ease-in-out saturate-200 hue-rotate-20; + .blog .discreet .card-leather:not(:hover) { + @apply bg-primary-50 opacity-75 transition duration-500 ease-in-out ; } } } diff --git a/src/styles/scrollbar.css b/src/styles/scrollbar.css index 568c1b9..8d2735d 100644 --- a/src/styles/scrollbar.css +++ b/src/styles/scrollbar.css @@ -1,13 +1,12 @@ @layer components { /* Global scrollbar styles */ * { - scrollbar-width: thin; /* Firefox */ scrollbar-color: rgba(87, 66, 41, 0.8) transparent; /* Transparent track, default scrollbar thumb */ } /* Webkit Browsers (Chrome, Safari, Edge) */ *::-webkit-scrollbar { - width: 8px; /* Thin scrollbar */ + width: 12px; /* Thin scrollbar */ } *::-webkit-scrollbar-track { From 1da1065471bb3c539a806e5eafe65434cd6f672e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nu=C5=A1a=20Puk=C5=A1i=C4=8D?= Date: Mon, 5 May 2025 14:41:06 +0200 Subject: [PATCH 07/21] Layout issues - make content fill screen and move publication navi again --- src/routes/+layout.svelte | 2 +- src/routes/publication/+page.svelte | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 8e1a965..0fbba6b 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -40,7 +40,7 @@ -
+
diff --git a/src/routes/publication/+page.svelte b/src/routes/publication/+page.svelte index ac297c4..f0695e2 100644 --- a/src/routes/publication/+page.svelte +++ b/src/routes/publication/+page.svelte @@ -46,14 +46,14 @@ +{#key data} + +{/key}
{#await data.waitable} {:then} - {#key data} - - {/key} Date: Mon, 5 May 2025 14:42:19 +0200 Subject: [PATCH 08/21] Declutter publication navi --- src/lib/components/util/ArticleNav.svelte | 35 ++++++++++++----------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/lib/components/util/ArticleNav.svelte b/src/lib/components/util/ArticleNav.svelte index 8df36bf..2ac8780 100644 --- a/src/lib/components/util/ArticleNav.svelte +++ b/src/lib/components/util/ArticleNav.svelte @@ -1,6 +1,6 @@ \ No newline at end of file From 5f7236fb088a8601a7af994fc13511ce9eb817b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nu=C5=A1a=20Puk=C5=A1i=C4=8D?= Date: Mon, 5 May 2025 14:44:14 +0200 Subject: [PATCH 09/21] Better interactivity --- src/app.css | 5 ++-- src/lib/components/Publication.svelte | 39 ++++++++++----------------- src/lib/stores.ts | 1 - src/styles/publications.css | 2 +- 4 files changed, 17 insertions(+), 30 deletions(-) diff --git a/src/app.css b/src/app.css index 05539ad..20e1021 100644 --- a/src/app.css +++ b/src/app.css @@ -60,9 +60,8 @@ /* To scroll columns independently */ main.publication.blog { - display: flex; - flex-direction: column; - max-height: calc(100vh - 76px); + @apply min-h-full; + max-height: calc(100vh - 146px); } main.main-leather, diff --git a/src/lib/components/Publication.svelte b/src/lib/components/Publication.svelte index e1555cd..f8c0360 100644 --- a/src/lib/components/Publication.svelte +++ b/src/lib/components/Publication.svelte @@ -9,7 +9,6 @@ TextPlaceholder, Tooltip, } from "flowbite-svelte"; - import { CaretLeftOutline } from 'flowbite-svelte-icons'; import { getContext, onMount } from "svelte"; import type { NDKEvent } from "@nostr-dev-kit/ndk"; import PublicationSection from "./PublicationSection.svelte"; @@ -78,6 +77,10 @@ } } + function isInnerActive() { + return currentBlog !== null && $publicationColumnVisibility.inner; + } + function loadBlog(rootId: string) { // depending on the size of the screen, also toggle blog list visibility if (window.innerWidth < 1024) { @@ -89,10 +92,7 @@ console.log(currentBlog); } - function backToMain() { - $publicationColumnVisibility.blog = true; - $publicationColumnVisibility.inner = false; - } + onMount(() => { // Set up the intersection observer. @@ -112,19 +112,11 @@ -{#if $publicationColumnVisibility.details} -
-
-
-
-
-{/if} - {#if isDefaultVisible()} -
+
@@ -136,7 +128,7 @@ rootId={leaf.tagAddress()} event={leaf} onBlogUpdate={loadBlog} - active={!(currentBlog !== null && $publicationColumnVisibility.inner)} + active={!(isInnerActive())} /> {/each} {:else} @@ -150,15 +142,12 @@ {/each} {/if} -
+
{/if} -{#if currentBlog !== null && $publicationColumnVisibility.inner } +{#if isInnerActive() } {#key currentBlog } -
-
- -
+
{#each leaves as leaf, i} {#if leaf.tagAddress() === currentBlog} +
{/if} diff --git a/src/lib/stores.ts b/src/lib/stores.ts index a78e275..f158e66 100644 --- a/src/lib/stores.ts +++ b/src/lib/stores.ts @@ -8,7 +8,6 @@ export let alexandriaKinds = readable([30040, 30041, 30818]); export let feedType = writable(FeedType.StandardRelays); export const publicationColumnVisibility = writable({ - details: false, toc: false, blog: true, main: true, diff --git a/src/styles/publications.css b/src/styles/publications.css index 5616bd0..d901db8 100644 --- a/src/styles/publications.css +++ b/src/styles/publications.css @@ -254,7 +254,7 @@ @screen lg { @media (hover: hover) { .blog .discreet .card-leather:not(:hover) { - @apply bg-primary-50 opacity-75 transition duration-500 ease-in-out ; + @apply bg-primary-50 dark:bg-primary-1000 opacity-75 transition duration-500 ease-in-out ; } } } From 1a537239ed4065e9c227481c5b1e36e72e95f06f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nu=C5=A1a=20Puk=C5=A1i=C4=8D?= Date: Mon, 5 May 2025 17:04:14 +0200 Subject: [PATCH 10/21] More dynamic and reactive columns --- src/app.css | 3 +- src/lib/components/Publication.svelte | 34 ++++++++++++-- src/lib/components/blog/BlogHeader.svelte | 11 ++--- src/lib/components/util/ArticleNav.svelte | 51 +++++++++++++++------ src/lib/components/util/Interactions.svelte | 2 +- 5 files changed, 73 insertions(+), 28 deletions(-) diff --git a/src/app.css b/src/app.css index 20e1021..79655e8 100644 --- a/src/app.css +++ b/src/app.css @@ -60,7 +60,7 @@ /* To scroll columns independently */ main.publication.blog { - @apply min-h-full; + @apply w-full sm:w-auto min-h-full; max-height: calc(100vh - 146px); } @@ -380,7 +380,6 @@ .line-ellipsis { max-width: 100%; - white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } \ No newline at end of file diff --git a/src/lib/components/Publication.svelte b/src/lib/components/Publication.svelte index f8c0360..9d5c228 100644 --- a/src/lib/components/Publication.svelte +++ b/src/lib/components/Publication.svelte @@ -1,6 +1,6 @@ \ No newline at end of file diff --git a/src/lib/components/util/Interactions.svelte b/src/lib/components/util/Interactions.svelte index 4263f05..a605c06 100644 --- a/src/lib/components/util/Interactions.svelte +++ b/src/lib/components/util/Interactions.svelte @@ -5,7 +5,7 @@ import { onMount } from "svelte"; import { ndkInstance } from '$lib/ndk'; - const { rootId, event } = $props<{ rootId: String, event: NDKEvent }>(); + const { rootId, event } = $props<{ rootId: string, event: NDKEvent }>(); // Reactive arrays to hold incoming events let likes: NDKEvent[] = []; From 5283ebf1a77b53b6ba372b23803b4d8b40164c46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nu=C5=A1a=20Puk=C5=A1i=C4=8D?= Date: Tue, 6 May 2025 15:48:28 +0200 Subject: [PATCH 11/21] Added hashtags and interaction counters, changed layouts --- src/app.css | 12 +++- src/lib/components/Login.svelte | 2 +- src/lib/components/Publication.svelte | 70 ++++++++++++++++---- src/lib/components/blog/BlogHeader.svelte | 18 +++-- src/lib/components/util/ArticleNav.svelte | 27 ++++---- src/lib/components/util/CardActions.svelte | 4 +- src/lib/components/util/Details.svelte | 60 ++++++++++++----- src/lib/components/util/InlineProfile.svelte | 2 +- src/lib/components/util/Interactions.svelte | 25 +++++-- src/lib/components/util/TocToggle.svelte | 4 +- src/lib/stores.ts | 2 +- src/routes/+layout.svelte | 6 +- src/styles/base.css | 8 ++- src/styles/publications.css | 3 + 14 files changed, 176 insertions(+), 67 deletions(-) diff --git a/src/app.css b/src/app.css index 79655e8..ae4ac69 100644 --- a/src/app.css +++ b/src/app.css @@ -1,5 +1,5 @@ @import './styles/base.css'; -@import 'styles/scrollbar.css'; +@import './styles/scrollbar.css'; @import './styles/publications.css'; @import './styles/visualize.css'; @@ -58,10 +58,13 @@ @apply max-w-full flex; } + main.publication { + @apply mt-[70px]; + } + /* To scroll columns independently */ main.publication.blog { @apply w-full sm:w-auto min-h-full; - max-height: calc(100vh - 146px); } main.main-leather, @@ -259,6 +262,10 @@ @apply max-h-72; } + .tags span { + @apply bg-primary-50 text-primary-800 text-sm font-medium me-2 px-2.5 py-0.5 rounded-sm dark:bg-primary-900 dark:text-primary-200; + } + } @layer components { @@ -379,7 +386,6 @@ } .line-ellipsis { - max-width: 100%; overflow: hidden; text-overflow: ellipsis; } \ No newline at end of file diff --git a/src/lib/components/Login.svelte b/src/lib/components/Login.svelte index 1456149..0149a0d 100644 --- a/src/lib/components/Login.svelte +++ b/src/lib/components/Login.svelte @@ -46,7 +46,7 @@ {#if $ndkSignedIn} {:else} - + import { - Button, Card, Img, + Button, Card, Sidebar, SidebarGroup, SidebarItem, SidebarWrapper, Skeleton, TextPlaceholder, - Tooltip, + Tooltip } from "flowbite-svelte"; - import { getContext, onMount } from "svelte"; + import { HeartOutline } from 'flowbite-svelte-icons'; + import { getContext, onDestroy, onMount } from "svelte"; 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/blog/BlogHeader.svelte"; + import Interactions from "$components/util/Interactions.svelte"; + import ZapOutline from "$components/util/ZapOutline.svelte"; let { rootAddress, publicationType, indexEvent } = $props<{ rootAddress: string, @@ -83,14 +86,14 @@ } function isSocialActive() { - return $publicationColumnVisibility.social; + return $publicationColumnVisibility.discussion; } function loadBlog(rootId: string) { // depending on the size of the screen, also toggle blog list & social visibility if (window.innerWidth < 1024) { $publicationColumnVisibility.blog = false; - $publicationColumnVisibility.social = false; + $publicationColumnVisibility.discussion = false; } $publicationColumnVisibility.inner = true; currentBlog = rootId; @@ -98,9 +101,8 @@ currentBlogEvent = leaves.find(i => i.tagAddress() === currentBlog) ?? null; } - function showBlogHeaderOnMobile() { - return (currentBlog && currentBlogEvent && window.innerWidth < 1024); + return (currentBlog && currentBlogEvent && window.innerWidth < 1140); } onMount(() => { @@ -119,6 +121,18 @@ }; }); + onDestroy(() => { + // reset visibility + $publicationColumnVisibility = { + toc: false, + blog: true, + main: true, + inner: true, + discussion: false, + editing: false + }; + }) + {#if isDefaultVisible()} @@ -156,15 +170,23 @@ {#if isInnerActive() } {#key currentBlog } -
+
{#each leaves as leaf, i} {#if leaf.tagAddress() === currentBlog} +
+
+
+ setLastElementRef(el, i)} /> + + + + {/if} {/each}
@@ -172,7 +194,7 @@ {/if} {#if isSocialActive() } -
+
{#if showBlogHeaderOnMobile()} {/if} -
+
-
+
+ Unknown + 1.1.1970 +
- This is a placeholder comment... + This is a very intelligent comment placeholder that applies to all the content equally well. +
+ + + +
+ Unknown + 1.1.1970 +
+
+ +
+
+ + +
+ Unknown + 1.1.1970 +
+
+
-
diff --git a/src/lib/components/blog/BlogHeader.svelte b/src/lib/components/blog/BlogHeader.svelte index b5f1ff3..f7fc25b 100644 --- a/src/lib/components/blog/BlogHeader.svelte +++ b/src/lib/components/blog/BlogHeader.svelte @@ -5,6 +5,7 @@ import InlineProfile from "$components/util/InlineProfile.svelte"; import Interactions from "$components/util/Interactions.svelte"; import { quintOut } from "svelte/easing"; + import CardActions from "$components/util/CardActions.svelte"; const { rootId, event, onBlogUpdate, active = true } = $props<{ rootId: string, event: NDKEvent, onBlogUpdate?: any, active: boolean }>(); @@ -12,6 +13,7 @@ let author: string = $derived(event.getMatchingTags('author')[0]?.[1] ?? 'unknown'); let image: string = $derived(event.getMatchingTags('image')[0]?.[1] ?? null); let authorPubkey: string = $derived(event.getMatchingTags('p')[0]?.[1] ?? null); + let hashtags: string = $derived(event.getMatchingTags('t') ?? null); function publishedAt() { const date = event.created_at ? new Date(event.created_at * 1000) : ''; @@ -35,8 +37,11 @@
- - {publishedAt()} +
+ + {publishedAt()} +
+
{#if image && active}
showBlog()} class='text-left'>

{title}

+ {#if hashtags} +
+ {#each hashtags as tag} + {tag} + {/each} +
+ {/if}
{#if active} -
-
{/if}
diff --git a/src/lib/components/util/ArticleNav.svelte b/src/lib/components/util/ArticleNav.svelte index d89d372..d220f50 100644 --- a/src/lib/components/util/ArticleNav.svelte +++ b/src/lib/components/util/ArticleNav.svelte @@ -22,13 +22,16 @@ let pubkey: string = $derived(indexEvent.getMatchingTags('p')[0]?.[1] ?? null); // Function to toggle column visibility - function toggleColumn(column: 'blog'|'inner'|'social') { + function toggleColumn(column: 'blog'|'inner'|'discussion') { publicationColumnVisibility.update(store => { store[column] = !store[column]; // Toggle true/false - if (window.innerWidth < 1400 && $publicationColumnVisibility.social) { + if (window.innerWidth < 1400 && column === 'discussion' && $publicationColumnVisibility.discussion) { $publicationColumnVisibility.blog = false; } - if (window.innerWidth < 1200) { + if (window.innerWidth < 1400 && column === 'blog' && $publicationColumnVisibility.blog) { + $publicationColumnVisibility.discussion = false; + } + if (window.innerWidth < 980) { $publicationColumnVisibility.inner = false; } return { ...store }; // Ensure reactivity @@ -36,23 +39,23 @@ } function backToMain() { - if ($publicationColumnVisibility.social) { + if ($publicationColumnVisibility.discussion) { $publicationColumnVisibility.inner = true; - $publicationColumnVisibility.social = false; + $publicationColumnVisibility.discussion = false; } else { $publicationColumnVisibility.blog = true; $publicationColumnVisibility.inner = false; - $publicationColumnVisibility.social = false; + $publicationColumnVisibility.discussion = false; } } -