clone of repo on github
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

262 lines
8.0 KiB

<script lang="ts">
import {
BookOutline,
CaretLeftOutline,
CloseOutline,
GlobeOutline,
ChartOutline,
} from "flowbite-svelte-icons";
import { Button, P } from "flowbite-svelte";
import { publicationColumnVisibility } from "$lib/stores";
import { userBadge } from "$lib/snippets/UserSnippets.svelte";
import type { NDKEvent } from "@nostr-dev-kit/ndk";
import { onDestroy, onMount } from "svelte";
import { goto } from "$app/navigation";
import { page } from "$app/stores";
import { indexKind } from "$lib/consts";
import { getNdkContext } from "$lib/ndk";
const ndk = getNdkContext();
let { publicationType, indexEvent } = $props<{
rootId: any;
publicationType: string;
indexEvent: NDKEvent;
}>();
let title: string = $derived(indexEvent.getMatchingTags("title")[0]?.[1]);
let author: string = $derived(
indexEvent.getMatchingTags("author")[0]?.[1] ?? "unknown",
);
let pubkey: string = $derived(
indexEvent.getMatchingTags("p")[0]?.[1] ?? null,
);
let isLeaf: boolean = $derived(indexEvent.kind === 30041);
let isIndexEvent: boolean = $derived(indexEvent.kind === indexKind);
let lastScrollY = $state(0);
let isVisible = $state(true);
let navbarTop = $state(100); // Default to 100px
// Function to toggle column visibility
function toggleColumn(column: "toc" | "blog" | "inner" | "discussion") {
console.log("[ArticleNav] toggleColumn called with:", column);
publicationColumnVisibility.update((current) => {
const newValue = !current[column];
console.log("[ArticleNav] Toggling", column, "from", current[column], "to", newValue);
const updated = { ...current, [column]: newValue };
if (window.innerWidth < 1400 && column === "blog" && newValue) {
updated.discussion = false;
}
return updated;
});
}
function shouldShowBack() {
const vis = $publicationColumnVisibility;
return ["discussion", "toc", "inner"].some(
(key) => vis[key as keyof typeof vis],
);
}
function backToMain() {
publicationColumnVisibility.update((current) => {
const updated = { ...current };
// if current is 'inner', just go back to blog
if (current.inner && !(current.discussion || current.toc)) {
updated.inner = false;
updated.blog = true;
return updated;
}
updated.discussion = false;
updated.toc = false;
if (publicationType === "blog") {
updated.inner = true;
updated.blog = false;
} else {
updated.main = true;
}
return updated;
});
}
function backToBlog() {
publicationColumnVisibility.update((current) => {
const updated = { ...current };
updated.inner = false;
updated.discussion = false;
updated.blog = true;
return updated;
});
}
function handleBlogTocClick() {
if ($publicationColumnVisibility.inner) {
// Viewing article: go back to TOC
backToBlog();
} else if ($publicationColumnVisibility.blog) {
// Showing TOC: toggle it (though it should stay visible)
toggleColumn("blog");
}
}
function handleScroll() {
if (window.innerWidth < 768) {
const currentScrollY = window.scrollY;
// Hide on scroll down
if (currentScrollY > lastScrollY && currentScrollY > 50) {
isVisible = false;
}
// Show on scroll up
else if (currentScrollY < lastScrollY) {
isVisible = true;
}
lastScrollY = currentScrollY;
}
}
// Check if user came from visualization page
let cameFromVisualization = $derived.by(() => {
const url = $page.url;
return url.searchParams.has('from') && url.searchParams.get('from') === 'visualize';
});
function visualizePublication() {
// Use the event ID directly, but also try to get the tagAddress as a fallback
const eventId = indexEvent.id;
const tagAddress = indexEvent.tagAddress();
// For debugging, log both identifiers
console.log("[ArticleNav] Visualizing publication:", {
eventId,
tagAddress,
kind: indexEvent.kind,
pubkey: indexEvent.pubkey
});
goto(`/visualize?event=${eventId}`);
}
function returnToVisualization() {
// Go back to visualization page
goto('/visualize');
}
let unsubscribe: () => void;
onMount(() => {
// Measure the actual navbar height to position ArticleNav correctly
const navbar = document.getElementById("navi");
if (navbar) {
const rect = navbar.getBoundingClientRect();
navbarTop = rect.bottom;
}
window.addEventListener("scroll", handleScroll);
unsubscribe = publicationColumnVisibility.subscribe(() => {
isVisible = true; // show navbar when store changes
});
});
onDestroy(() => {
window.removeEventListener("scroll", handleScroll);
unsubscribe();
});
</script>
<nav
class="Navbar navbar-leather col-span-2 flex fixed w-full min-h-[70px] px-2 sm:px-4 py-2.5 z-10 transition-transform duration-300 {isVisible
? 'translate-y-0'
: '-translate-y-full'}"
style="top: {navbarTop}px;"
>
<div class="mx-auto flex space-x-2 container">
<div class="flex items-center space-x-2 md:min-w-52 min-w-8">
{#if isIndexEvent}
{#if publicationType === "blog"}
<!-- Blog view: disabled when showing blog list, active when viewing article -->
<Button
class={`btn-leather !w-auto ${$publicationColumnVisibility.inner ? "active" : ""}`}
outline={true}
disabled={$publicationColumnVisibility.blog && !$publicationColumnVisibility.inner}
onclick={handleBlogTocClick}
title={$publicationColumnVisibility.inner ? "Back to Table of Contents" : "Table of Contents"}
>
<BookOutline class="!fill-none" />
</Button>
{:else if !$publicationColumnVisibility.discussion}
<Button
class={`btn-leather !w-auto ${$publicationColumnVisibility.toc ? "active" : ""}`}
outline={true}
onclick={() => toggleColumn("toc")}
title="Table of Contents"
>
<BookOutline class="!fill-none" />
</Button>
{/if}
{/if}
</div>
<div class="flex flex-col flex-grow text justify-center items-center">
<P class="max-w-[60vw] line-ellipsis">
<b class="text-nowrap">{title}</b>
</P>
<P>
<span class="whitespace-nowrap"
>by {@render userBadge(pubkey, author, ndk)}</span
>
</P>
</div>
<div class="flex justify-end items-center space-x-2 md:min-w-52 min-w-8">
{#if $publicationColumnVisibility.inner}
<Button
class="btn-leather !w-auto hidden sm:flex"
outline={true}
onclick={backToBlog}
>
<CloseOutline class="!fill-none inline mr-1" />
<span class="hidden sm:inline">Close</span>
</Button>
{/if}
{#if !$publicationColumnVisibility.discussion}
<Button
class="btn-leather !hidden sm:flex !w-auto"
outline={true}
onclick={() => toggleColumn("discussion")}
>
<GlobeOutline class="!fill-none inline mr-1" />
<span class="hidden sm:inline">Discussion</span>
</Button>
{/if}
{#if cameFromVisualization}
<Button
class="btn-leather !w-auto"
outline={true}
onclick={returnToVisualization}
title="Return to visualization"
>
<CaretLeftOutline class="!fill-none inline mr-1" /><span
class="hidden sm:inline">Return to Visualization</span
>
</Button>
{:else if isIndexEvent}
<Button
class="btn-leather !w-auto"
outline={true}
onclick={visualizePublication}
title="Visualize publication network"
>
<ChartOutline class="!fill-none inline mr-1" /><span
class="hidden sm:inline">Visualize Publication</span
>
</Button>
{/if}
</div>
</div>
</nav>