Something went wrong. Try again.
Monorepo for Tangled forked from tangled.org/core
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101<script lang="ts"> import { page } from "$app/state"; import { resolve } from "$app/paths"; import Check from "$icon/check"; import Mail from "$icon/mail"; import X from "$icon/x"; import { createAction, createLoad } from "#lib/action.svelte.ts"; import { ClientResponseError } from "#lib/api/client.ts"; import { createDeliberiClient } from "#lib/api/deliberi.ts"; import { dismissNewsletter, getNewsletterStatus, subscribeNewsletter } from "#lib/api/newsletter.ts"; import { getAuth } from "#lib/auth.svelte.ts"; import PreviewCard from "#lib/components/timeline/PreviewCard.svelte"; import Button from "#lib/components/ui/Button.svelte";
const auth = getAuth(); const deliberi = () => { const agent = auth.agent; const deliberiUrl = page.data.publicConfig?.deliberiUrl as string | undefined; return agent && deliberiUrl ? createDeliberiClient({ deliberiUrl, agent }) : null; };
// stays hidden while loading or on failure; it's a prompt, not content const status = createLoad(async () => { const ctx = deliberi(); return ctx ? ((await getNewsletterStatus(ctx)) ?? "unset") : null; });
let dismissed = $state(false);
const subscribe = createAction( async () => { const ctx = deliberi(); if (!ctx) throw new Error("Your session is still loading. Try again."); await subscribeNewsletter(ctx); return true; }, () => "Couldn't sign you up. Try again later." ); const needsEmail = $derived( subscribe.cause instanceof ClientResponseError && subscribe.cause.error === "NoVerifiedPrimaryEmail" );
// fire and forget like the old widget: a failed write only brings the card back next visit const dismiss = () => { dismissed = true; const ctx = deliberi(); if (ctx) dismissNewsletter(ctx).catch(() => {}); };</script>
{#if status.data === "unset" && !dismissed} <div data-testid="newsletterCard"> <PreviewCard title="Newsletter" icon={Mail}> {#snippet action()} <Button variant="ghost" size="small" square icon={X} aria-label="Dismiss" class="self-stretch [--btn-radius:var(--radius-md)]" onclick={dismiss} /> {/snippet} <div class="flex flex-col gap-sm p-sm typography-paragraph-small"> <p class="text-foreground-default"> We've got a newsletter! Get updates on what we're shipping at Tangled, sent to your primary email. </p> {#if subscribe.data} <p class="flex items-center gap-xs text-foreground-success" role="status"> <Check class="size-3.5" aria-hidden="true" /> You're signed up! </p> {:else} <Button class="self-start" loading={subscribe.loading} onclick={() => subscribe.run()} > Subscribe </Button> {#if needsEmail} <p class="text-foreground-danger" role="alert"> Add and verify an email address in <a href={resolve("/settings/emails")}>settings</a> first. </p> {:else if subscribe.error} <p class="text-foreground-danger" role="alert">{subscribe.error}</p> {/if} {/if} </div> </PreviewCard> </div>{/if}