Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
Svelte
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104<script lang="ts"> import { browser } from "$app/environment"; import { resolve } from "$app/paths"; import ArrowRight from "$icon/arrow-right"; import Bell from "$icon/bell"; import BellOff from "$icon/bell-off"; import Inbox from "$icon/inbox"; import { createLoad } from "$lib/action.svelte"; import NotificationList from "$lib/components/notifications/NotificationList.svelte"; import type { NotificationSummary } from "$lib/components/notifications/types"; import { getNotifications, type Notifications } from "$lib/notifications.svelte"; import PreviewCard from "$lib/components/timeline/PreviewCard.svelte"; import PreviewEmpty from "$lib/components/timeline/PreviewEmpty.svelte"; import timelineNotificationspreviewSkeletonFixture from "$lib/bones/timeline-notificationspreview--skeleton-fixture.bones.json"; import Bones from "$lib/components/ui/Bones.svelte"; import Button from "$lib/components/ui/Button.svelte";
const PREVIEW_LIMIT = 5;
let { signedIn = false, notifications: fixtures }: { signedIn?: boolean; notifications?: NotificationSummary[] | Promise<NotificationSummary[]>; } = $props();
const context = getNotifications() as Notifications | undefined; const path = "/notifications";
const fixturePreview = $derived.by(() => { if (!fixtures) return undefined; if (fixtures instanceof Promise) return fixtures; return { notifications: fixtures, totalUnread: fixtures.filter((n) => !n.read).length }; });
const previewLoad = createLoad(async (): Promise<NotificationSummary[] | null> => { if (!browser || !signedIn || !context) return null; return context.list({ limit: PREVIEW_LIMIT }); });
const live = $derived( previewLoad.data ? (context?.overlay(previewLoad.data) ?? previewLoad.data) : null );
const loading = $derived( signedIn && fixtures === undefined && (previewLoad.loading || previewLoad.data === undefined) );</script>
{#snippet content(items: NotificationSummary[], totalUnread: number | null)} {#if items.length > 0} <NotificationList notifications={items} border={false} grouped={false} onToggleRead={context?.setRead} /> {:else if totalUnread === 0} <PreviewEmpty icon={Inbox}> <p>All caught up!</p> </PreviewEmpty> {:else} <PreviewEmpty icon={Bell}> <a href={resolve(path as "/")}>Open your inbox</a> </PreviewEmpty> {/if}{/snippet}
<PreviewCard title="Notifications" icon={Bell} href={path}> {#snippet action()} <Button href={resolve(path as "/")} variant="ghost" size="small"> View all <ArrowRight class="size-3.5" aria-hidden="true" /> </Button> {/snippet}
{#if !signedIn} <PreviewEmpty icon={BellOff}> <a href={resolve("/login" as "/")}>Log in</a> to view your inbox </PreviewEmpty> {:else if loading} <Bones capture={timelineNotificationspreviewSkeletonFixture} /> {:else if fixturePreview} {#if fixturePreview instanceof Promise} {#await fixturePreview} <Bones capture={timelineNotificationspreviewSkeletonFixture} /> {:then resolved} {@render content(resolved, null)} {/await} {:else} {@render content(fixturePreview.notifications, fixturePreview.totalUnread)} {/if} {:else if live} {@render content(live, context?.unread ?? null)} {:else} <PreviewEmpty icon={Bell}> <a href={resolve(path as "/")}>Open your inbox</a> </PreviewEmpty> {/if}</PreviewCard>