Browse Source

Intermediate state where publications have 'covers' and columns are still all messed up

master
Nuša Pukšič 11 months ago
parent
commit
6d7f4217ee
  1. 14
      src/app.css
  2. 21
      src/lib/components/Preview.svelte
  3. 17
      src/lib/components/Publication.svelte
  4. 65
      src/lib/components/blog/BlogHeader.svelte
  5. 74
      src/lib/components/util/ArticleNav.svelte
  6. 6
      src/lib/components/util/Details.svelte
  7. 4
      src/routes/publication/+page.svelte

14
src/app.css

@ -55,11 +55,12 @@
/* Content */ /* Content */
main { main {
@apply max-w-full flex; @apply max-w-full flex mb-2;
} }
main.blog { /* To scroll columns independently */
max-height: calc(100vh - 130px); main.publication {
/* max-height: calc(100vh - 130px); */
} }
main.main-leather, main.main-leather,
@ -219,3 +220,10 @@
@apply bg-primary-0 dark:bg-primary-1000 text-gray-800 dark:text-gray-300; @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;
}

21
src/lib/components/Preview.svelte

@ -4,6 +4,7 @@
import { CaretDownSolid, CaretUpSolid, EditOutline } from 'flowbite-svelte-icons'; import { CaretDownSolid, CaretUpSolid, EditOutline } from 'flowbite-svelte-icons';
import Self from './Preview.svelte'; import Self from './Preview.svelte';
import { contentParagraph, sectionHeading } from '$lib/snippets/PublicationSnippets.svelte'; import { contentParagraph, sectionHeading } from '$lib/snippets/PublicationSnippets.svelte';
import BlogHeader from "./blog/BlogHeader.svelte";
// TODO: Fix move between parents. // TODO: Fix move between parents.
@ -93,6 +94,10 @@
} }
}); });
function getBlogEvent(index: number) {
return blogEntries[index][1];
}
function byline(rootId: string, index: number) { function byline(rootId: string, index: number) {
console.log(rootId, index, blogEntries); console.log(rootId, index, blogEntries);
const event = blogEntries[index][1]; const event = blogEntries[index][1];
@ -198,7 +203,7 @@
{#snippet sectionHeading(title: string, depth: number)} {#snippet sectionHeading(title: string, depth: number)}
{@const headingLevel = Math.min(depth + 1, 6)} {@const headingLevel = Math.min(depth + 1, 6)}
{@const className = $pharosInstance.isFloatingTitle(rootId) ? 'discrete' : 'h-leather'} {@const className = $pharosInstance.isFloatingTitle(rootId) ? 'discrete' : 'h-leather'}
<svelte:element this={`h${headingLevel}`} class={className}> <svelte:element this={`h${headingLevel}`} class={className}>
{title} {title}
</svelte:element> </svelte:element>
@ -221,12 +226,6 @@
</p> </p>
{/snippet} {/snippet}
{#snippet readMoreLink(rootId: string, index: number)}
<p class='h-leather'>
<button class="underline" onclick={() => readBlog(rootId)}>Read all about it...</button>
</p>
{/snippet}
{#snippet contentParagraph(content: string, publicationType: string)} {#snippet contentParagraph(content: string, publicationType: string)}
{#if publicationType === 'novel'} {#if publicationType === 'novel'}
<P class='whitespace-normal' firstupper={isSectionStart}> <P class='whitespace-normal' firstupper={isSectionStart}>
@ -294,17 +293,13 @@
</Button> </Button>
</ButtonGroup> </ButtonGroup>
{:else} {:else}
{#if publicationType === 'blog' && depth === 1} {#if !(publicationType === 'blog' && depth === 1)}
{@render coverImage(rootId, index, depth)}
{@render sectionHeading(title!, depth)}
{@render blogMetadata(rootId, index)}
{:else}
{@render sectionHeading(title!, depth)} {@render sectionHeading(title!, depth)}
{/if} {/if}
{/if} {/if}
<!-- Recurse on child indices and zettels --> <!-- Recurse on child indices and zettels -->
{#if publicationType === 'blog' && depth === 1} {#if publicationType === 'blog' && depth === 1}
{@render readMoreLink(rootId, index)} <BlogHeader event={getBlogEvent(index)} rootId={rootId} onBlogUpdate={readBlog} />
{:else } {:else }
{#key subtreeUpdateCount} {#key subtreeUpdateCount}
{#each orderedChildren as id, index} {#each orderedChildren as id, index}

17
src/lib/components/Publication.svelte

@ -1,8 +1,6 @@
<script lang="ts"> <script lang="ts">
import Preview from "./Preview.svelte"; import Preview from "./Preview.svelte";
import { pharosInstance } from "$lib/parser"; import { pharosInstance } from "$lib/parser";
import { page } from "$app/state";
import { ndkInstance } from "$lib/ndk";
import type { NDKEvent } from "@nostr-dev-kit/ndk"; import type { NDKEvent } from "@nostr-dev-kit/ndk";
import Details from "$components/util/Details.svelte"; import Details from "$components/util/Details.svelte";
import { publicationColumnVisibility } from "$lib/stores"; import { publicationColumnVisibility } from "$lib/stores";
@ -17,7 +15,6 @@
console.error("Root ID does not match parser root index ID"); console.error("Root ID does not match parser root index ID");
} }
let activeHash = $state(page.url.hash);
let currentBlog: null|string = $state(null); let currentBlog: null|string = $state(null);
@ -40,8 +37,10 @@
</script> </script>
{#if $publicationColumnVisibility.details} {#if $publicationColumnVisibility.details}
<div class="flex flex-col space-y-4 max-w-xl flex-grow-1 p-2 bg-highlight"> <div class="flex flex-col space-y-4 max-w-xl min-w-24 sm:min-w-36 sm:flex-grow-1 p-2 overflow-auto">
<Details event={indexEvent} /> <div class="card-leather bg-highlight dark:bg-primary-800 p-4 mx-2 rounded-lg border">
<Details event={indexEvent} />
</div>
</div> </div>
{/if} {/if}
@ -50,6 +49,10 @@
{publicationType === 'blog' ? 'max-w-xl flex-grow-1' : 'max-w-2xl flex-grow-2' } {publicationType === 'blog' ? 'max-w-xl flex-grow-1' : 'max-w-2xl flex-grow-2' }
{currentBlog !== null ? 'discreet' : ''} {currentBlog !== null ? 'discreet' : ''}
"> ">
<div class="card-leather bg-highlight dark:bg-primary-800 p-4 mx-2 mb-4 rounded-lg border">
<Details event={indexEvent} />
</div>
<Preview {rootId} {publicationType} index={0} onBlogUpdate={loadBlog} /> <Preview {rootId} {publicationType} index={0} onBlogUpdate={loadBlog} />
</div> </div>
{/if} {/if}
@ -63,8 +66,8 @@
{/if} {/if}
{#if $publicationColumnVisibility.social } {#if $publicationColumnVisibility.social }
<div class="flex flex-col space-y-4 max-w-xl overflow-auto flex-grow-1 bg-highlight"> <div class="flex flex-col space-y-4 max-w-xl overflow-auto flex-grow-1">
<p>Social column</p>
</div> </div>
{/if} {/if}

65
src/lib/components/blog/BlogHeader.svelte

@ -0,0 +1,65 @@
<script lang="ts">
import type { NDKEvent } from '@nostr-dev-kit/ndk';
import { Card, Img } from "flowbite-svelte";
import InlineProfile from "$components/util/InlineProfile.svelte";
import { HeartOutline } from 'flowbite-svelte-icons';
const { rootId, event, onBlogUpdate } = $props<{ rootId: String, event: NDKEvent, onBlogUpdate?: any; }>();
let title: string = $derived(event.getMatchingTags('title')[0]?.[1]);
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 likeCount = 0;
function publishedAt() {
const date = event.created_at ? new Date(event.created_at * 1000) : '';
if (date !== '') {
const formattedDate = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "short",
day: "2-digit",
}).format(date);
return formattedDate ?? "";
}
return '';
}
function showBlog() {
onBlogUpdate?.(rootId);
}
</script>
{#if title != null}
<Card class='ArticleBox card-leather w-xl flex flex-col'>
<div class='flex flex-col space-y-2'>
<div class="flex flex-row justify-between my-2">
<InlineProfile pubkey={authorPubkey} title={author} />
<span class='text-gray-500'>{publishedAt()}</span>
</div>
{#if image}
<div class="flex col justify-center">
<Img src={image} class="rounded w-full h-full object-cover"/>
</div>
{/if}
<div class='flex flex-col flex-grow space-y-4'>
<button onclick={() => showBlog()} class='text-left'>
<h2 class='text-lg font-bold line-clamp-2' title="{title}">{title}</h2>
</button>
<button class="underline text-right" onclick={() => showBlog()} >Read all about it...</button>
</div>
<div class='flex flex-row bg-primary-50'>
<div class='InteractiveMenu flex flex-row'>
<div class='flex flex-row shrink-0'><HeartOutline /><span>{likeCount}</span></div>
<div class='flex flex-row shrink-0'><HeartOutline /><span>{likeCount}</span></div>
<div class='flex flex-row shrink-0'><HeartOutline /><span>{likeCount}</span></div>
<div class='flex flex-row shrink-0'><HeartOutline /><span>{likeCount}</span></div>
<div class='flex flex-row shrink-0'><HeartOutline /><span>{likeCount}</span></div>
</div>
</div>
</div>
</Card>
{/if}

74
src/lib/components/util/ArticleNav.svelte

@ -1,24 +1,42 @@
<script lang="ts"> <script lang="ts">
import { pharosInstance } from "$lib/parser";
import TocToggle from "$components/util/TocToggle.svelte"; import TocToggle from "$components/util/TocToggle.svelte";
import { EyeOutline, BookOutline, AlignCenterOutline, BookOpenOutline, GlobeOutline, ShareAllOutline, PenOutline } from "flowbite-svelte-icons"; import { EyeOutline, BookOutline, BookOpenOutline, GlobeOutline } from "flowbite-svelte-icons";
import { Button } from "flowbite-svelte"; import { Button } from "flowbite-svelte";
import { onMount } from "svelte";
import { publicationColumnVisibility } from "$lib/stores"; import { publicationColumnVisibility } from "$lib/stores";
import InlineProfile from "$components/util/InlineProfile.svelte"; import InlineProfile from "$components/util/InlineProfile.svelte";
import type { NDKEvent } from "@nostr-dev-kit/ndk"; 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 { let {
rootId, rootId,
publicationType publicationType,
indexEvent
} = $props<{ } = $props<{
rootId: any, rootId: any,
publicationType: string publicationType: string,
indexEvent: NDKEvent
}>(); }>();
onMount(async () => { let title: string = $derived(indexEvent.getMatchingTags('title')[0]?.[1]);
console.log($pharosInstance.getIndexMetadata()); let author: string = $derived(indexEvent.getMatchingTags('author')[0]?.[1] ?? 'unknown');
}); let pubkey: string = $derived(indexEvent.getMatchingTags('p')[0]?.[1] ?? null);
// Function to toggle column visibility // Function to toggle column visibility
function toggleColumn(column: 'details'|'blog'|'inner'|'social') { function toggleColumn(column: 'details'|'blog'|'inner'|'social') {
@ -33,23 +51,31 @@
</script> </script>
<nav class="Navbar navbar-leather sticky top-[76px] w-full px-2 sm:px-4 py-2.5 z-10"> <nav class="Navbar navbar-leather sticky top-[75px] w-full min-h-[70px] px-2 sm:px-4 py-2.5 z-10">
<div class="mx-auto flex flex-wrap justify-center space-x-2 container"> <div class="mx-auto flex flex-wrap justify-around space-x-2 container">
<Button class='btn-leather !w-auto' outline={true} onclick={() => toggleColumn('details')} > {#if scrollY < 100}
<EyeOutline class="!fill-none inline mr-1" /><span class="hidden sm:inline">Details</span> <div class="buttons" transition:fade={{ duration: 300 }}>
</Button> <Button class='btn-leather !w-auto hidden' outline={true} onclick={() => toggleColumn('details')} >
{#if publicationType === 'blog'} <EyeOutline class="!fill-none inline mr-1" /><span class="hidden sm:inline">Details</span>
<Button class='btn-leather !w-auto' outline={true} onclick={() => toggleColumn('blog')} >
<BookOutline class="!fill-none inline mr-1" /><span class="hidden sm:inline">Table of Contents</span>
</Button> </Button>
<Button class='btn-leather !w-auto' outline={true} onclick={() => toggleColumn('inner')} > {#if publicationType === 'blog'}
<BookOpenOutline class="!fill-none inline mr-1" /><span class="hidden sm:inline">Content</span> <Button class='btn-leather !w-auto hidden' outline={true} onclick={() => toggleColumn('blog')} >
<BookOutline class="!fill-none inline mr-1" /><span class="hidden sm:inline">Table of Contents</span>
</Button>
<Button class='btn-leather !w-auto hidden' outline={true} onclick={() => toggleColumn('inner')} >
<BookOpenOutline class="!fill-none inline mr-1" /><span class="hidden sm:inline">Content</span>
</Button>
{:else}
<TocToggle rootId={rootId} />
{/if}
<Button class='btn-leather !w-auto hidden' outline={true} onclick={() => toggleColumn('social')} >
<GlobeOutline class="!fill-none inline mr-1" /><span class="hidden sm:inline">Social</span>
</Button> </Button>
{:else} </div>
<TocToggle rootId={rootId} /> {:else if scrollY > 200 }
{/if} <div class="text max-w-full" transition:fade={{ duration: 300 }}>
<Button class='btn-leather !w-auto' outline={true} onclick={() => toggleColumn('social')} > <p class="line-ellipsis"><b>{title}</b><br><span>by <InlineProfile pubkey={pubkey} title={author} /></span></p>
<GlobeOutline class="!fill-none inline mr-1" /><span class="hidden sm:inline">Social</span> </div>
</Button> {/if}
</div> </div>
</nav> </nav>

6
src/lib/components/util/Details.svelte

@ -37,18 +37,18 @@
</div> </div>
{#if summary} {#if summary}
<div class="flex flex-row "> <div class="flex flex-row my-2">
<p class='text-base text-primary-900 dark:text-highlight'>{summary}</p> <p class='text-base text-primary-900 dark:text-highlight'>{summary}</p>
</div> </div>
{/if} {/if}
<div class="flex flex-row "> <div class="flex flex-row my-4">
<h4 class='text-base font-normal mt-2'>Index author: <InlineProfile pubkey={event.pubkey} /></h4> <h4 class='text-base font-normal mt-2'>Index author: <InlineProfile pubkey={event.pubkey} /></h4>
</div> </div>
<div class="flex flex-col pb-4 space-y-1"> <div class="flex flex-col pb-4 space-y-1">
{#if source !== null} {#if source !== null}
<h5 class="text-sm">Source: <a class="underline" href={source} target="_blank">{source}</a></h5> <h5 class="text-sm">Source: <a class="underline break-all" href={source} target="_blank">{source}</a></h5>
{/if} {/if}
{#if type !== null} {#if type !== null}
<h5 class="text-sm">Publication type: {type}</h5> <h5 class="text-sm">Publication type: {type}</h5>

4
src/routes/publication/+page.svelte

@ -51,10 +51,10 @@
</svelte:head> </svelte:head>
{#key data} {#key data}
<ArticleNav publicationType={data.publicationType} rootId={data.parser.getRootIndexId()} /> <ArticleNav publicationType={data.publicationType} rootId={data.parser.getRootIndexId()} indexEvent={data.indexEvent} />
{/key} {/key}
<main class={data.publicationType}> <main class="publication {data.publicationType}">
{#await data.waitable} {#await data.waitable}
<TextPlaceholder divClass='skeleton-leather w-full' size="xxl" /> <TextPlaceholder divClass='skeleton-leather w-full' size="xxl" />
{:then} {:then}

Loading…
Cancel
Save