Add new claymorphic component library

This commit is contained in:
2026-06-23 17:44:30 +00:00
parent fd4e7a9f2d
commit 949359dca5
291 changed files with 6460 additions and 2581 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import type {Snippet} from "svelte" import type {Snippet} from "svelte"
import {pubkey} from "@welshman/app" import {pubkey} from "@welshman/app"
import Dialog from "@lib/components/Dialog.svelte" import Dialog from "@lib/components2/Dialog.svelte"
import Landing from "@app/components/Landing.svelte" import Landing from "@app/components/Landing.svelte"
import Toast from "@app/components/Toast.svelte" import Toast from "@app/components/Toast.svelte"
import PrimaryNav from "@app/components/PrimaryNav.svelte" import PrimaryNav from "@app/components/PrimaryNav.svelte"
+3 -2
View File
@@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components2/Spinner.svelte"
import Text from "@lib/components2/Text.svelte"
import QRCode from "@app/components/QRCode.svelte" import QRCode from "@app/components/QRCode.svelte"
import type {Nip46Controller} from "@app/nip46" import type {Nip46Controller} from "@app/nip46"
@@ -19,7 +20,7 @@
{:else} {:else}
<div class="flex flex-col items-center gap-2"> <div class="flex flex-col items-center gap-2">
<QRCode code={$url} /> <QRCode code={$url} />
<p class="text-sm opacity-75">Scan with your signer to log in, or click to copy.</p> <Text size="sm" muted>Scan with your signer to log in, or click to copy.</Text>
</div> </div>
{/if} {/if}
{/if} {/if}
+7 -7
View File
@@ -1,11 +1,11 @@
<script lang="ts"> <script lang="ts">
import {debounce} from "throttle-debounce" import {debounce} from "throttle-debounce"
import Scanner from "@lib/components/Scanner.svelte" import Scanner from "@lib/components2/Scanner.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Field from "@lib/components/Field.svelte" import Field from "@lib/components2/Field.svelte"
import CpuBolt from "@assets/icons/cpu-bolt.svg?dataurl" import CpuBolt from "@assets/icons/cpu-bolt.svg?dataurl"
import QrCode from "@assets/icons/qr-code.svg?dataurl" import QrCode from "@assets/icons/qr-code.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import InfoBunker from "@app/components/InfoBunker.svelte" import InfoBunker from "@app/components/InfoBunker.svelte"
import type {Nip46Controller} from "@app/nip46" import type {Nip46Controller} from "@app/nip46"
import {pushModal} from "@app/modal" import {pushModal} from "@app/modal"
@@ -34,9 +34,9 @@
<p>Bunker Link*</p> <p>Bunker Link*</p>
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<label class="input input-bordered flex w-full items-center gap-2"> <label class="input-cl input-cl-group">
<Icon icon={CpuBolt} /> <Icon icon={CpuBolt} />
<input disabled={$loading} bind:value={$bunker} class="grow" placeholder="bunker://" /> <input disabled={$loading} bind:value={$bunker} placeholder="bunker://" />
<Button onclick={toggleScanner}> <Button onclick={toggleScanner}>
<Icon icon={QrCode} /> <Icon icon={QrCode} />
</Button> </Button>
@@ -45,7 +45,7 @@
{#snippet info()} {#snippet info()}
<p> <p>
A login link provided by a nostr signing app. A login link provided by a nostr signing app.
<Button class="link" onclick={() => pushModal(InfoBunker)}>What is a bunker link?</Button> <Button class="cl-link" onclick={() => pushModal(InfoBunker)}>What is a bunker link?</Button>
</p> </p>
{/snippet} {/snippet}
</Field> </Field>
@@ -3,9 +3,9 @@
import {getTagValue, getAddress} from "@welshman/util" import {getTagValue, getAddress} from "@welshman/util"
import {pubkey} from "@welshman/app" import {pubkey} from "@welshman/app"
import Pen2 from "@assets/icons/pen-2.svg?dataurl" import Pen2 from "@assets/icons/pen-2.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components2/Link.svelte"
import RoomName from "@app/components/RoomName.svelte" import RoomName from "@app/components/RoomName.svelte"
import ReactionSummary from "@app/components/ReactionSummary.svelte" import ReactionSummary from "@app/components/ReactionSummary.svelte"
import ThunkStatusOrDeleted from "@app/components/ThunkStatusOrDeleted.svelte" import ThunkStatusOrDeleted from "@app/components/ThunkStatusOrDeleted.svelte"
@@ -42,11 +42,11 @@
<div class="flex grow flex-wrap justify-end gap-2"> <div class="flex grow flex-wrap justify-end gap-2">
{#if h && showRoom} {#if h && showRoom}
<Link href={makeSpacePath(url, h)} class="btn btn-neutral btn-xs rounded-full"> <Link href={makeSpacePath(url, h)} class="badge-cl badge-cl-neutral badge-cl-sm">
Posted in #<RoomName {h} {url} /> Posted in #<RoomName {h} {url} />
</Link> </Link>
{/if} {/if}
<ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="tooltip-left" /> <ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="cl-tip-left" />
<ThunkStatusOrDeleted {event} /> <ThunkStatusOrDeleted {event} />
{#if showActivity} {#if showActivity}
<EventActivity {url} {path} {event} /> <EventActivity {url} {path} {event} />
@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import CalendarEventForm from "@app/components/CalendarEventForm.svelte" import CalendarEventForm from "@app/components/CalendarEventForm.svelte"
type Props = { type Props = {
+2 -2
View File
@@ -14,10 +14,10 @@
{#if !isNaN(start)} {#if !isNaN(start)}
{@const startDate = secondsToDate(start)} {@const startDate = secondsToDate(start)}
<div <div
class="hidden h-32 w-32 min-w-32 flex-col items-center justify-center gap-1 rounded-box bg-base-300 p-2 sm:flex"> class="clay-card clay-card-sm cl-surface-alt hidden h-32 w-32 min-w-32 flex-col items-center justify-center gap-1 p-2 sm:flex">
<strong>{Intl.DateTimeFormat(LOCALE, {month: "short"}).format(startDate)}</strong> <strong>{Intl.DateTimeFormat(LOCALE, {month: "short"}).format(startDate)}</strong>
<span class="text-4xl">{Intl.DateTimeFormat(LOCALE, {day: "numeric"}).format(startDate)}</span> <span class="text-4xl">{Intl.DateTimeFormat(LOCALE, {day: "numeric"}).format(startDate)}</span>
<span class="text-xs opacity-75" <span class="cl-text-muted text-xs"
>{Intl.DateTimeFormat(LOCALE, {weekday: "long"}).format(startDate)}</span> >{Intl.DateTimeFormat(LOCALE, {weekday: "long"}).format(startDate)}</span>
</div> </div>
{/if} {/if}
+3 -3
View File
@@ -1,9 +1,9 @@
<script lang="ts"> <script lang="ts">
import type {TrustedEvent} from "@welshman/util" import type {TrustedEvent} from "@welshman/util"
import {getTagValue} from "@welshman/util" import {getTagValue} from "@welshman/util"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import CalendarEventForm from "@app/components/CalendarEventForm.svelte" import CalendarEventForm from "@app/components/CalendarEventForm.svelte"
type Props = { type Props = {
+17 -18
View File
@@ -9,14 +9,14 @@
import GallerySend from "@assets/icons/gallery-send.svg?dataurl" import GallerySend from "@assets/icons/gallery-send.svg?dataurl"
import MapPoint from "@assets/icons/map-point.svg?dataurl" import MapPoint from "@assets/icons/map-point.svg?dataurl"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Field from "@lib/components/Field.svelte" import Field from "@lib/components2/Field.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components2/Spinner.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components2/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import DateTimeInput from "@lib/components/DateTimeInput.svelte" import DateTimeInput from "@lib/components2/DateTimeInput.svelte"
import EditorContent from "@app/editor/EditorContent.svelte" import EditorContent from "@app/editor/EditorContent.svelte"
import {PROTECTED, publishRoomQuote} from "@app/groups" import {PROTECTED, publishRoomQuote} from "@app/groups"
import {makeEditor} from "@app/editor" import {makeEditor} from "@app/editor"
@@ -164,8 +164,8 @@
<p>Title*</p> <p>Title*</p>
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<label class="input input-bordered flex w-full items-center gap-2"> <label class="input-cl input-cl-group">
<input bind:value={title} class="grow" type="text" /> <input bind:value={title} type="text" />
</label> </label>
{/snippet} {/snippet}
</Field> </Field>
@@ -174,18 +174,17 @@
<p>Summary</p> <p>Summary</p>
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<div <div class="cl-surface cl-border-t relative z-feature flex gap-2">
class="relative z-feature flex gap-2 border-t border-solid border-base-100 bg-base-100">
<div class="input-editor grow overflow-hidden"> <div class="input-editor grow overflow-hidden">
<EditorContent {editor} /> <EditorContent {editor} />
</div> </div>
<Button <Button
data-tip="Add an image" data-tip="Add an image"
class="center btn tooltip" circle
onclick={selectFiles} onclick={selectFiles}
disabled={loading}> disabled={loading}>
{#if $uploading} {#if $uploading}
<span class="loading loading-spinner loading-xs"></span> <span class="cl-spinner"></span>
{:else} {:else}
<Icon icon={GallerySend} /> <Icon icon={GallerySend} />
{/if} {/if}
@@ -214,19 +213,19 @@
<p>Location (optional)</p> <p>Location (optional)</p>
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<label class="input input-bordered flex w-full items-center gap-2"> <label class="input-cl input-cl-group">
<Icon icon={MapPoint} /> <Icon icon={MapPoint} />
<input bind:value={location} class="grow" type="text" /> <input bind:value={location} type="text" />
</label> </label>
{/snippet} {/snippet}
</Field> </Field>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back} disabled={loading}> <Button variant="ghost" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
<Button type="submit" class="btn btn-primary" disabled={$uploading || loading}> <Button type="submit" variant="primary" disabled={$uploading || loading}>
<Spinner loading={$uploading || loading}>Save Event</Spinner> <Spinner loading={$uploading || loading}>Save Event</Spinner>
</Button> </Button>
</ModalFooter> </ModalFooter>
@@ -7,7 +7,8 @@
} from "@welshman/lib" } from "@welshman/lib"
import type {TrustedEvent} from "@welshman/util" import type {TrustedEvent} from "@welshman/util"
import ClockCircle from "@assets/icons/clock-circle.svg?dataurl" import ClockCircle from "@assets/icons/clock-circle.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Text from "@lib/components2/Text.svelte"
type Props = { type Props = {
event: TrustedEvent event: TrustedEvent
@@ -20,12 +21,12 @@
</script> </script>
<div class="flex flex-col justify-between gap-1"> <div class="flex flex-col justify-between gap-1">
<p class="text-lg">{meta.title || meta.name}</p> <Text size="lg">{meta.title || meta.name}</Text>
{#if !isNaN(start) && !isNaN(end)} {#if !isNaN(start) && !isNaN(end)}
{@const startDateDisplay = formatTimestampAsDate(start)} {@const startDateDisplay = formatTimestampAsDate(start)}
{@const endDateDisplay = formatTimestampAsDate(end)} {@const endDateDisplay = formatTimestampAsDate(end)}
{@const isSingleDay = startDateDisplay === endDateDisplay} {@const isSingleDay = startDateDisplay === endDateDisplay}
<div class="flex flex-wrap gap-2 text-xs"> <div class="cl-text flex flex-wrap gap-2 text-xs">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<Icon icon={ClockCircle} size={4} /> <Icon icon={ClockCircle} size={4} />
{formatTimestampAsDate(start)} {formatTimestampAsDate(start)}
+3 -3
View File
@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import type {TrustedEvent} from "@welshman/util" import type {TrustedEvent} from "@welshman/util"
import {getTagValue, getAddress} from "@welshman/util" import {getTagValue, getAddress} from "@welshman/util"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components2/Link.svelte"
import CalendarEventActions from "@app/components/CalendarEventActions.svelte" import CalendarEventActions from "@app/components/CalendarEventActions.svelte"
import CalendarEventHeader from "@app/components/CalendarEventHeader.svelte" import CalendarEventHeader from "@app/components/CalendarEventHeader.svelte"
import ProfileLink from "@app/components/ProfileLink.svelte" import ProfileLink from "@app/components/ProfileLink.svelte"
@@ -19,11 +19,11 @@
</script> </script>
<Link <Link
class="cv col-3 card2 bg-alt w-full cursor-pointer shadow-md" class="cv clay-card clay-card-interactive flex w-full cursor-pointer flex-col gap-3 p-4 sm:p-6"
href={makeCalendarPath(url, getAddress(event))}> href={makeCalendarPath(url, getAddress(event))}>
<CalendarEventHeader {event} /> <CalendarEventHeader {event} />
<div class="flex w-full flex-col items-end justify-between gap-2 sm:flex-row"> <div class="flex w-full flex-col items-end justify-between gap-2 sm:flex-row">
<span class="whitespace-nowrap py-1 text-sm opacity-75"> <span class="cl-text-muted whitespace-nowrap py-1 text-sm">
Posted by <ProfileLink pubkey={event.pubkey} {url} /> Posted by <ProfileLink pubkey={event.pubkey} {url} />
{#if h} {#if h}
in <RoomLink {url} {h} /> in <RoomLink {url} {h} />
+2 -2
View File
@@ -3,7 +3,7 @@
import type {TrustedEvent} from "@welshman/util" import type {TrustedEvent} from "@welshman/util"
import UserCircle from "@assets/icons/user-circle.svg?dataurl" import UserCircle from "@assets/icons/user-circle.svg?dataurl"
import MapPoint from "@assets/icons/map-point.svg?dataurl" import MapPoint from "@assets/icons/map-point.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import ProfileLink from "@app/components/ProfileLink.svelte" import ProfileLink from "@app/components/ProfileLink.svelte"
type Props = { type Props = {
@@ -15,7 +15,7 @@
const meta = $derived(fromPairs(event.tags) as Record<string, string>) const meta = $derived(fromPairs(event.tags) as Record<string, string>)
</script> </script>
<div class="flex min-w-0 flex-col gap-1 text-sm opacity-75"> <div class="cl-text-muted flex min-w-0 flex-col gap-1 text-sm">
<span class="flex items-center gap-1"> <span class="flex items-center gap-1">
<Icon icon={UserCircle} size={4} /> <Icon icon={UserCircle} size={4} />
Posted by <ProfileLink pubkey={event.pubkey} {url} /> Posted by <ProfileLink pubkey={event.pubkey} {url} />
+31 -25
View File
@@ -36,12 +36,16 @@
} from "@welshman/app" } from "@welshman/app"
import Danger from "@assets/icons/danger-triangle.svg?dataurl" import Danger from "@assets/icons/danger-triangle.svg?dataurl"
import ArrowLeft from "@assets/icons/arrow-left.svg?dataurl" import ArrowLeft from "@assets/icons/arrow-left.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components2/Spinner.svelte"
import PageBar from "@lib/components/PageBar.svelte" import PageBar from "@lib/components2/PageBar.svelte"
import PageContent from "@lib/components/PageContent.svelte" import PageContent from "@lib/components2/PageContent.svelte"
import Divider from "@lib/components/Divider.svelte" import Divider from "@lib/components2/Divider.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Row from "@lib/components2/Row.svelte"
import Col from "@lib/components2/Col.svelte"
import Card from "@lib/components2/Card.svelte"
import Text from "@lib/components2/Text.svelte"
import ProfileName from "@app/components/ProfileName.svelte" import ProfileName from "@app/components/ProfileName.svelte"
import ProfileLink from "@app/components/ProfileLink.svelte" import ProfileLink from "@app/components/ProfileLink.svelte"
import ProfileCircle from "@app/components/ProfileCircle.svelte" import ProfileCircle from "@app/components/ProfileCircle.svelte"
@@ -249,18 +253,18 @@
<Icon icon={ArrowLeft} size={7} /> <Icon icon={ArrowLeft} size={7} />
</Button> </Button>
<div class="flex items-center justify-between gap-4"> <div class="flex items-center justify-between gap-4">
<div class="ellipsize flex items-center gap-4 whitespace-nowrap"> <div class="flex items-center gap-4 overflow-hidden text-ellipsis whitespace-nowrap">
<Button class="flex flex-col gap-1 sm:flex-row sm:gap-2" onclick={showMembers}> <Button class="flex flex-col gap-1 sm:flex-row sm:gap-2" onclick={showMembers}>
{#if others.length === 0} {#if others.length === 0}
<div class="row-2"> <Row>
<ProfileCircle pubkey={$pubkey!} size={5} /> <ProfileCircle pubkey={$pubkey!} size={5} />
<ProfileName pubkey={$pubkey!} /> <ProfileName pubkey={$pubkey!} />
</div> </Row>
{:else if others.length === 1} {:else if others.length === 1}
<div class="row-2"> <Row>
<ProfileCircle pubkey={others[0]} size={5} /> <ProfileCircle pubkey={others[0]} size={5} />
<ProfileName pubkey={others[0]} /> <ProfileName pubkey={others[0]} />
</div> </Row>
{:else} {:else}
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<ProfileCircles pubkeys={others} size={5} /> <ProfileCircles pubkeys={others} size={5} />
@@ -285,19 +289,21 @@
<PageContent class="flex flex-col-reverse gap-2 py-2 !mb-0"> <PageContent class="flex flex-col-reverse gap-2 py-2 !mb-0">
{#if missingRelayLists.length > 0} {#if missingRelayLists.length > 0}
<div class="py-12"> <div class="py-12">
<div class="card2 col-2 m-auto max-w-md items-center text-center"> <Card class="m-auto max-w-md text-center">
<p class="row-2 text-lg text-error"> <Col class="items-center">
<Icon icon={Danger} /> <Row class="text-lg cl-text-danger">
Direct messages are not enabled <Icon icon={Danger} />
</p> Direct messages are not enabled
<p> </Row>
Ask <Text>
{#each missingRelayLists as pubkey (pubkey)} Ask
<ProfileLink {pubkey} /> {#each missingRelayLists as pubkey (pubkey)}
{/each} <ProfileLink {pubkey} />
to enable direct messaging by opening this conversation in their app. {/each}
</p> to enable direct messaging by opening this conversation in their app.
</div> </Text>
</Col>
</Card>
</div> </div>
{/if} {/if}
{#each elements as { type, id, value, showPubkey } (id)} {#each elements as { type, id, value, showPubkey } (id)}
@@ -326,7 +332,7 @@
<div class="h-screen"></div> <div class="h-screen"></div>
</PageContent> </PageContent>
<div class="chat__compose bg-base-200"> <div class="chat__compose cl-surface-alt">
<div> <div>
{#if parent} {#if parent}
<ChatComposeParent event={parent} clear={clearParent} verb="Replying to" /> <ChatComposeParent event={parent} clear={clearParent} verb="Replying to" />
+9 -5
View File
@@ -6,8 +6,8 @@
import {isMobile, preventDefault} from "@lib/html" import {isMobile, preventDefault} from "@lib/html"
import GallerySend from "@assets/icons/gallery-send.svg?dataurl" import GallerySend from "@assets/icons/gallery-send.svg?dataurl"
import Plane from "@assets/icons/plane-2.svg?dataurl" import Plane from "@assets/icons/plane-2.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import EditorContent from "@app/editor/EditorContent.svelte" import EditorContent from "@app/editor/EditorContent.svelte"
import {makeEditor} from "@app/editor" import {makeEditor} from "@app/editor"
import {type DraftKey} from "@app/drafts" import {type DraftKey} from "@app/drafts"
@@ -112,12 +112,14 @@
<form class="relative z-feature flex gap-2 p-2" onsubmit={preventDefault(submit)}> <form class="relative z-feature flex gap-2 p-2" onsubmit={preventDefault(submit)}>
<Button <Button
variant="secondary"
circle
data-tip="Add an image" data-tip="Add an image"
class="center tooltip tooltip-right h-10 w-10 min-w-10 rounded-box bg-base-300 transition-colors hover:bg-base-200" class="h-10 w-10 min-w-10"
disabled={$uploading || disabled} disabled={$uploading || disabled}
onclick={uploadFiles}> onclick={uploadFiles}>
{#if $uploading} {#if $uploading}
<span class="loading loading-spinner loading-xs"></span> <span class="cl-spinner"></span>
{:else} {:else}
<Icon icon={GallerySend} /> <Icon icon={GallerySend} />
{/if} {/if}
@@ -126,8 +128,10 @@
<EditorContent {autofocus} {editor} /> <EditorContent {autofocus} {editor} />
</div> </div>
<Button <Button
variant="primary"
circle
data-tip="{window.navigator.platform.includes('Mac') ? 'cmd' : 'ctrl'}+enter to send" data-tip="{window.navigator.platform.includes('Mac') ? 'cmd' : 'ctrl'}+enter to send"
class="center tooltip tooltip-left absolute right-4 h-10 w-10 min-w-10 rounded-full" class="absolute right-4 h-10 w-10 min-w-10"
disabled={$uploading || disabled} disabled={$uploading || disabled}
onclick={submit}> onclick={submit}>
<Icon icon={Plane} /> <Icon icon={Plane} />
+5 -4
View File
@@ -1,8 +1,8 @@
<script lang="ts"> <script lang="ts">
import {slide} from "@lib/transition" import {slide} from "@lib/transition"
import CloseCircle from "@assets/icons/close-circle.svg?dataurl" import CloseCircle from "@assets/icons/close-circle.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
const { const {
clear, clear,
@@ -12,9 +12,10 @@
</script> </script>
<div <div
class="relative flex h-8 items-center justify-between border-l-2 border-solid border-primary bg-base-300 px-2 pr-7 text-xs" class="relative flex h-8 items-center justify-between border-l-2 border-solid px-2 pr-7 text-xs cl-surface-alt cl-text-primary"
style="border-left-color: var(--cl-primary);"
transition:slide> transition:slide>
<p class="text-primary">Editing message</p> <p>Editing message</p>
<Button onclick={clear} class="flex items-center"> <Button onclick={clear} class="flex items-center">
<Icon icon={CloseCircle} /> <Icon icon={CloseCircle} />
</Button> </Button>
+5 -4
View File
@@ -3,8 +3,8 @@
import {displayProfileByPubkey} from "@welshman/app" import {displayProfileByPubkey} from "@welshman/app"
import {slide} from "@lib/transition" import {slide} from "@lib/transition"
import CloseCircle from "@assets/icons/close-circle.svg?dataurl" import CloseCircle from "@assets/icons/close-circle.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import NoteContentMinimal from "@app/components/NoteContentMinimal.svelte" import NoteContentMinimal from "@app/components/NoteContentMinimal.svelte"
const { const {
@@ -19,9 +19,10 @@
</script> </script>
<div <div
class="relative border-l-2 border-solid border-primary bg-base-300 px-2 py-1 pr-8" class="relative border-l-2 border-solid px-2 py-1 pr-8 cl-surface-alt"
style="border-left-color: var(--cl-primary);"
transition:slide> transition:slide>
<p class="text-xs text-primary">{verb} @{displayProfileByPubkey(event.pubkey)}</p> <p class="text-xs cl-text-primary">{verb} @{displayProfileByPubkey(event.pubkey)}</p>
{#key event.id} {#key event.id}
<NoteContentMinimal trimParent {event} /> <NoteContentMinimal trimParent {event} />
{/key} {/key}
+12 -11
View File
@@ -4,14 +4,15 @@
import {preventDefault} from "@lib/html" import {preventDefault} from "@lib/html"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components2/Spinner.svelte"
import Modal from "@lib/components/Modal.svelte" import Text from "@lib/components2/Text.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalFooter from "@lib/components2/ModalFooter.svelte"
import {DEFAULT_RELAYS, DEFAULT_MESSAGING_RELAYS} from "@app/env" import {DEFAULT_RELAYS, DEFAULT_MESSAGING_RELAYS} from "@app/env"
import {pushToast} from "@app/toast" import {pushToast} from "@app/toast"
@@ -57,14 +58,14 @@
<ModalHeader> <ModalHeader>
<ModalTitle>Enable direct messaging?</ModalTitle> <ModalTitle>Enable direct messaging?</ModalTitle>
</ModalHeader> </ModalHeader>
<p>Direct messaging isn't currently enabled. Would you like to turn it on?</p> <Text>Direct messaging isn't currently enabled. Would you like to turn it on?</Text>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button variant="ghost" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
<Button type="submit" class="btn btn-primary" disabled={loading}> <Button type="submit" variant="primary" disabled={loading}>
<Spinner {loading}>Enable direct messaging</Spinner> <Spinner {loading}>Enable direct messaging</Spinner>
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
+16 -6
View File
@@ -1,3 +1,9 @@
<style>
.chat-item:hover {
background-color: var(--cl-bg-alt);
}
</style>
<script lang="ts"> <script lang="ts">
import {onMount} from "svelte" import {onMount} from "svelte"
import {page} from "$app/stores" import {page} from "$app/stores"
@@ -5,7 +11,7 @@
import type {TrustedEvent} from "@welshman/util" import type {TrustedEvent} from "@welshman/util"
import {pubkey, loadMessagingRelayList} from "@welshman/app" import {pubkey, loadMessagingRelayList} from "@welshman/app"
import {fade} from "@lib/transition" import {fade} from "@lib/transition"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import ProfileName from "@app/components/ProfileName.svelte" import ProfileName from "@app/components/ProfileName.svelte"
import ProfileCircle from "@app/components/ProfileCircle.svelte" import ProfileCircle from "@app/components/ProfileCircle.svelte"
import ProfileCircles from "@app/components/ProfileCircles.svelte" import ProfileCircles from "@app/components/ProfileCircles.svelte"
@@ -35,8 +41,8 @@
<Button class="flex flex-col justify-start gap-1 w-full" onclick={openChat}> <Button class="flex flex-col justify-start gap-1 w-full" onclick={openChat}>
<div <div
class="cursor-pointer border-t border-solid border-base-100 px-3 py-2 transition-colors hover:bg-base-100 {props.class}" class="chat-item cursor-pointer cl-border-t px-3 py-2 transition-colors {props.class}"
class:bg-base-100={active}> class:cl-surface-alt={active}>
<div class="flex flex-col justify-start gap-1"> <div class="flex flex-col justify-start gap-1">
<div class="flex items-center justify-between gap-2"> <div class="flex items-center justify-between gap-2">
<div class="flex min-w-0 items-center gap-2"> <div class="flex min-w-0 items-center gap-2">
@@ -56,18 +62,22 @@
{/if} {/if}
</div> </div>
{#if !active && $notifications.has(path)} {#if !active && $notifications.has(path)}
<div class="h-2 w-2 rounded-full bg-primary" transition:fade></div> <div
class="h-2 w-2 rounded-full"
style="background-color: var(--cl-primary);"
transition:fade>
</div>
{/if} {/if}
</div> </div>
<p class="overflow-hidden text-ellipsis whitespace-nowrap text-sm"> <p class="overflow-hidden text-ellipsis whitespace-nowrap text-sm">
<span class="opacity-70"> <span class="cl-text-muted">
{#if props.messages[0].pubkey === $pubkey} {#if props.messages[0].pubkey === $pubkey}
You: You:
{/if} {/if}
</span> </span>
{props.messages[0].content} {props.messages[0].content}
</p> </p>
<p class="text-xs opacity-70"> <p class="text-xs cl-text-muted">
{formatTimestamp(props.messages[0].created_at)} {formatTimestamp(props.messages[0].created_at)}
</p> </p>
</div> </div>
+10 -9
View File
@@ -1,10 +1,11 @@
<script lang="ts"> <script lang="ts">
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components2/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import Card from "@lib/components2/Card.svelte"
import Profile from "@app/components/Profile.svelte" import Profile from "@app/components/Profile.svelte"
interface Props { interface Props {
@@ -21,13 +22,13 @@
</ModalHeader> </ModalHeader>
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
{#each pubkeys as pubkey (pubkey)} {#each pubkeys as pubkey (pubkey)}
<div class="card2 bg-alt"> <Card sm pad={false} class="p-3">
<Profile {pubkey} /> <Profile {pubkey} />
</div> </Card>
{/each} {/each}
</div> </div>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button> <Button variant="primary" onclick={() => history.back()}>Got it</Button>
</ModalFooter> </ModalFooter>
</Modal> </Modal>
+7 -7
View File
@@ -3,10 +3,10 @@
import Check from "@assets/icons/check.svg?dataurl" import Check from "@assets/icons/check.svg?dataurl"
import Bell from "@assets/icons/bell.svg?dataurl" import Bell from "@assets/icons/bell.svg?dataurl"
import BellOff from "@assets/icons/bell-off.svg?dataurl" import BellOff from "@assets/icons/bell-off.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import {setChecked} from "@app/notifications" import {setChecked} from "@app/notifications"
import {notificationSettings} from "@app/settings" import {notificationSettings} from "@app/settings"
@@ -23,17 +23,17 @@
<Modal> <Modal>
<ModalBody> <ModalBody>
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<Button class="btn btn-neutral" onclick={markAsRead}> <Button variant="secondary" onclick={markAsRead}>
<Icon size={5} icon={Check} /> <Icon size={5} icon={Check} />
Mark all read Mark all read
</Button> </Button>
{#if $notificationSettings.messages} {#if $notificationSettings.messages}
<Button class="btn btn-neutral" onclick={disableAlerts}> <Button variant="secondary" onclick={disableAlerts}>
<Icon size={4} icon={BellOff} /> <Icon size={4} icon={BellOff} />
Disable alerts Disable alerts
</Button> </Button>
{:else} {:else}
<Button class="btn btn-neutral" onclick={enableAlerts}> <Button variant="secondary" onclick={enableAlerts}>
<Icon size={4} icon={Bell} /> <Icon size={4} icon={Bell} />
Enable alerts Enable alerts
</Button> </Button>
+10 -15
View File
@@ -5,10 +5,10 @@
import {thunks, mergeThunks, pubkey, deriveProfileDisplay, sendWrapped} from "@welshman/app" import {thunks, mergeThunks, pubkey, deriveProfileDisplay, sendWrapped} from "@welshman/app"
import {isMobile} from "@lib/html" import {isMobile} from "@lib/html"
import MenuDots from "@assets/icons/menu-dots.svg?dataurl" import MenuDots from "@assets/icons/menu-dots.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Tippy from "@lib/components/Tippy.svelte" import Tippy from "@lib/components2/Tippy.svelte"
import TapTarget from "@lib/components/TapTarget.svelte" import TapTarget from "@lib/components2/TapTarget.svelte"
import ProfileCircle from "@app/components/ProfileCircle.svelte" import ProfileCircle from "@app/components/ProfileCircle.svelte"
import Content from "@app/components/Content.svelte" import Content from "@app/components/Content.svelte"
import ReactionSummary from "@app/components/ReactionSummary.svelte" import ReactionSummary from "@app/components/ReactionSummary.svelte"
@@ -71,10 +71,8 @@
{/if} {/if}
<div <div
data-event={event.id} data-event={event.id}
class="group chat flex items-center justify-end gap-1 px-2" class="group flex items-center justify-end gap-1 px-2"
class:chat-start={!isOwn} class:flex-row-reverse={!isOwn}>
class:flex-row-reverse={!isOwn}
class:chat-end={isOwn}>
{#if !isMobile} {#if !isMobile}
<Tippy <Tippy
bind:popover bind:popover
@@ -101,16 +99,13 @@
{/if} {/if}
<div class="flex min-w-0 flex-col" class:items-end={isOwn}> <div class="flex min-w-0 flex-col" class:items-end={isOwn}>
<TapTarget <TapTarget
class="bg-alt chat-bubble mx-1 mb-2 flex cursor-auto flex-col gap-1 text-left lg:max-w-2xl min-w-[100px]" class="cl-surface-alt mx-1 mb-2 flex min-w-[100px] cursor-auto flex-col gap-1 rounded-2xl px-4 py-3 text-left lg:max-w-2xl"
onTap={showMobileMenu}> onTap={showMobileMenu}>
{#if showPubkey} {#if showPubkey}
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
{#if !isOwn} {#if !isOwn}
<Button onclick={openProfile} class="flex items-center gap-1"> <Button onclick={openProfile} class="flex items-center gap-1">
<ProfileCircle <ProfileCircle pubkey={event.pubkey} class="cl-border" size={4} />
pubkey={event.pubkey}
class="border border-solid border-base-content"
size={4} />
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<Button onclick={openProfile} class="text-sm font-bold" style="color: {colorValue}"> <Button onclick={openProfile} class="text-sm font-bold" style="color: {colorValue}">
{$profileDisplay} {$profileDisplay}
@@ -118,7 +113,7 @@
</div> </div>
</Button> </Button>
{/if} {/if}
<span class="whitespace-nowrap text-xs opacity-50" <span class="cl-text-subtle whitespace-nowrap text-xs"
>{formatTimestampAsTime(event.created_at)}</span> >{formatTimestampAsTime(event.created_at)}</span>
</div> </div>
{/if} {/if}
@@ -126,7 +121,7 @@
<Content showEntire {event} /> <Content showEntire {event} />
</div> </div>
</TapTarget> </TapTarget>
<div class="row-2 z-feature -mt-4 ml-4"> <div class="z-feature -mt-4 ml-4 flex items-center gap-2">
<ReactionSummary {event} {deleteReaction} {createReaction} noTooltip /> <ReactionSummary {event} {deleteReaction} {createReaction} noTooltip />
</div> </div>
</div> </div>
@@ -3,8 +3,8 @@
import type {TrustedEvent} from "@welshman/util" import type {TrustedEvent} from "@welshman/util"
import {sendWrapped} from "@welshman/app" import {sendWrapped} from "@welshman/app"
import SmileCircle from "@assets/icons/smile-circle.svg?dataurl" import SmileCircle from "@assets/icons/smile-circle.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import EmojiButton from "@lib/components/EmojiButton.svelte" import EmojiButton from "@lib/components2/EmojiButton.svelte"
import {makeReaction} from "@app/reactions" import {makeReaction} from "@app/reactions"
interface Props { interface Props {
@@ -22,6 +22,6 @@
}) })
</script> </script>
<EmojiButton {onEmoji} class="btn join-item btn-xs"> <EmojiButton {onEmoji} class="btn-cl-sm">
<Icon icon={SmileCircle} size={4} /> <Icon icon={SmileCircle} size={4} />
</EmojiButton> </EmojiButton>
+8 -7
View File
@@ -1,6 +1,7 @@
<script lang="ts"> <script lang="ts">
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Row from "@lib/components2/Row.svelte"
import ChatMessageEmojiButton from "@app/components/ChatMessageEmojiButton.svelte" import ChatMessageEmojiButton from "@app/components/ChatMessageEmojiButton.svelte"
import EventInfo from "@app/components/EventInfo.svelte" import EventInfo from "@app/components/EventInfo.svelte"
import {pushModal} from "@app/modal" import {pushModal} from "@app/modal"
@@ -19,19 +20,19 @@
} }
</script> </script>
<div class="join border border-solid border-neutral text-xs"> <Row gap={1} class="cl-surface cl-border rounded-full px-1 py-1 text-xs">
<ChatMessageEmojiButton {event} {pubkeys} /> <ChatMessageEmojiButton {event} {pubkeys} />
{#if replyTo} {#if replyTo}
<Button class="btn join-item btn-xs" onclick={reply}> <Button size="sm" circle onclick={reply}>
<Icon size={4} icon={Reply} /> <Icon size={4} icon={Reply} />
</Button> </Button>
{/if} {/if}
{#if edit} {#if edit}
<Button class="btn join-item btn-xs" onclick={onEdit}> <Button size="sm" circle onclick={onEdit}>
<Icon size={4} icon={Pen} /> <Icon size={4} icon={Pen} />
</Button> </Button>
{/if} {/if}
<Button class="btn join-item btn-xs" onclick={showInfo}> <Button size="sm" circle onclick={showInfo}>
<Icon size={4} icon={Code2} /> <Icon size={4} icon={Code2} />
</Button> </Button>
</div> </Row>
+13 -12
View File
@@ -7,11 +7,12 @@
import Reply from "@assets/icons/reply-2.svg?dataurl" import Reply from "@assets/icons/reply-2.svg?dataurl"
import Copy from "@assets/icons/copy.svg?dataurl" import Copy from "@assets/icons/copy.svg?dataurl"
import Code2 from "@assets/icons/code-2.svg?dataurl" import Code2 from "@assets/icons/code-2.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import EmojiPicker from "@lib/components/EmojiPicker.svelte" import Col from "@lib/components2/Col.svelte"
import EmojiPicker from "@lib/components2/EmojiPicker.svelte"
import EventInfo from "@app/components/EventInfo.svelte" import EventInfo from "@app/components/EventInfo.svelte"
import {makeReaction} from "@app/reactions" import {makeReaction} from "@app/reactions"
import {pushModal} from "@app/modal" import {pushModal} from "@app/modal"
@@ -57,29 +58,29 @@
<Modal> <Modal>
<ModalBody> <ModalBody>
<div class="flex flex-col gap-2"> <Col gap={2}>
<Button class="btn btn-neutral" onclick={showInfo}> <Button variant="secondary" onclick={showInfo}>
<Icon size={4} icon={Code2} /> <Icon size={4} icon={Code2} />
Message Info Message Info
</Button> </Button>
<Button class="btn btn-neutral w-full" onclick={copyText}> <Button variant="secondary" block onclick={copyText}>
<Icon size={4} icon={Copy} /> <Icon size={4} icon={Copy} />
Copy Text Copy Text
</Button> </Button>
<Button class="btn btn-neutral w-full" onclick={sendReply}> <Button variant="secondary" block onclick={sendReply}>
<Icon size={4} icon={Reply} /> <Icon size={4} icon={Reply} />
Send Reply Send Reply
</Button> </Button>
{#if edit} {#if edit}
<Button class="btn btn-neutral w-full" onclick={sendEdit}> <Button variant="secondary" block onclick={sendEdit}>
<Icon size={4} icon={Pen} /> <Icon size={4} icon={Pen} />
Edit Message Edit Message
</Button> </Button>
{/if} {/if}
<Button class="btn btn-primary w-full" onclick={showEmojiPicker}> <Button variant="primary" block onclick={showEmojiPicker}>
<Icon size={4} icon={SmileCircle} /> <Icon size={4} icon={SmileCircle} />
Send Reaction Send Reaction
</Button> </Button>
</div> </Col>
</ModalBody> </ModalBody>
</Modal> </Modal>
+11 -11
View File
@@ -6,17 +6,17 @@
import {fromNostrURI} from "@welshman/util" import {fromNostrURI} from "@welshman/util"
import {loadMessagingRelayList} from "@welshman/app" import {loadMessagingRelayList} from "@welshman/app"
import {preventDefault} from "@lib/html" import {preventDefault} from "@lib/html"
import Field from "@lib/components/Field.svelte" import Field from "@lib/components2/Field.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components2/ModalFooter.svelte"
import ProfileMultiSelect from "@app/components/ProfileMultiSelect.svelte" import ProfileMultiSelect from "@app/components/ProfileMultiSelect.svelte"
import {goToChat} from "@app/routes" import {goToChat} from "@app/routes"
@@ -73,11 +73,11 @@
</Field> </Field>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button variant="ghost" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
<Button type="submit" class="btn btn-primary" disabled={pubkeys.length === 0}> <Button type="submit" variant="primary" disabled={pubkeys.length === 0}>
Create Chat Create Chat
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
+10 -7
View File
@@ -5,9 +5,10 @@
import {pubkey} from "@welshman/app" import {pubkey} from "@welshman/app"
import Pen2 from "@assets/icons/pen-2.svg?dataurl" import Pen2 from "@assets/icons/pen-2.svg?dataurl"
import {normalizeTopic} from "@lib/util" import {normalizeTopic} from "@lib/util"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components2/Link.svelte"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Badge from "@lib/components2/Badge.svelte"
import RoomName from "@app/components/RoomName.svelte" import RoomName from "@app/components/RoomName.svelte"
import ReactionSummary from "@app/components/ReactionSummary.svelte" import ReactionSummary from "@app/components/ReactionSummary.svelte"
import ClassifiedStatus from "@app/components/ClassifiedStatus.svelte" import ClassifiedStatus from "@app/components/ClassifiedStatus.svelte"
@@ -46,18 +47,20 @@
<div class="flex grow flex-wrap justify-end gap-2"> <div class="flex grow flex-wrap justify-end gap-2">
{#if h && showRoom} {#if h && showRoom}
<Link href={makeSpacePath(url, h)} class="btn btn-neutral btn-xs rounded-full"> <Link href={makeSpacePath(url, h)}>
Posted in #<RoomName {h} {url} /> <Badge variant="neutral" sm>
Posted in #<RoomName {h} {url} />
</Badge>
</Link> </Link>
{/if} {/if}
<div class="flex min-w-0 flex-wrap gap-2"> <div class="flex min-w-0 flex-wrap gap-2">
{#each uniq(topics) as topic (topic)} {#each uniq(topics) as topic (topic)}
<button type="button" class="btn btn-xs rounded-full font-normal"> <button type="button" class="badge-cl badge-cl-neutral badge-cl-sm">
#{normalizeTopic(topic)} #{normalizeTopic(topic)}
</button> </button>
{/each} {/each}
</div> </div>
<ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="tooltip-left" /> <ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="cl-tip-left" />
<ThunkStatusOrDeleted {event}> <ThunkStatusOrDeleted {event}>
<ClassifiedStatus {event} /> <ClassifiedStatus {event} />
</ThunkStatusOrDeleted> </ThunkStatusOrDeleted>
+3 -3
View File
@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ClassifiedForm from "@app/components/ClassifiedForm.svelte" import ClassifiedForm from "@app/components/ClassifiedForm.svelte"
type Props = { type Props = {
+3 -3
View File
@@ -2,9 +2,9 @@
import {fromPairs} from "@welshman/lib" import {fromPairs} from "@welshman/lib"
import type {TrustedEvent} from "@welshman/util" import type {TrustedEvent} from "@welshman/util"
import {getTag, getTagValues} from "@welshman/util" import {getTag, getTagValues} from "@welshman/util"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ClassifiedForm from "@app/components/ClassifiedForm.svelte" import ClassifiedForm from "@app/components/ClassifiedForm.svelte"
type Props = { type Props = {
+28 -29
View File
@@ -6,14 +6,18 @@
import {isMobile, preventDefault} from "@lib/html" import {isMobile, preventDefault} from "@lib/html"
import {normalizeTopic} from "@lib/util" import {normalizeTopic} from "@lib/util"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Field from "@lib/components/Field.svelte" import Field from "@lib/components2/Field.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components2/Spinner.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import Col from "@lib/components2/Col.svelte"
import Modal from "@lib/components/Modal.svelte" import Grid from "@lib/components2/Grid.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import Input from "@lib/components2/Input.svelte"
import ImagesInput from "@lib/components/ImagesInput.svelte" import Select from "@lib/components2/Select.svelte"
import ModalFooter from "@lib/components2/ModalFooter.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import ImagesInput from "@lib/components2/ImagesInput.svelte"
import CurrencyInput from "@app/components/CurrencyInput.svelte" import CurrencyInput from "@app/components/CurrencyInput.svelte"
import TopicMultiSelect from "@app/components/TopicMultiSelect.svelte" import TopicMultiSelect from "@app/components/TopicMultiSelect.svelte"
import EditorContent from "@app/editor/EditorContent.svelte" import EditorContent from "@app/editor/EditorContent.svelte"
@@ -164,21 +168,18 @@
<Modal tag="form" onsubmit={preventDefault(submit)}> <Modal tag="form" onsubmit={preventDefault(submit)}>
<ModalBody> <ModalBody>
{@render header?.()} {@render header?.()}
<div class="col-8 relative"> <Col gap={8} class="relative">
<Field> <Field>
{#snippet label()} {#snippet label()}
<p>Title*</p> <p>Title*</p>
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<label class="input input-bordered flex w-full items-center gap-2"> <!-- svelte-ignore a11y_autofocus -->
<!-- svelte-ignore a11y_autofocus --> <Input
<input autofocus={!isMobile}
autofocus={!isMobile} bind:value={title}
bind:value={title} type="text"
class="grow" placeholder="What is this listing for?" />
type="text"
placeholder="What is this listing for?" />
</label>
{/snippet} {/snippet}
</Field> </Field>
<Field> <Field>
@@ -204,12 +205,10 @@
<p>Price*</p> <p>Price*</p>
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<div class="join grid grid-cols-2"> <Grid cols={2} gap={2}>
<label class="join-item input input-bordered flex w-full items-center gap-2"> <Input bind:value={price} type="number" />
<input bind:value={price} class="grow w-32" type="number" /> <CurrencyInput bind:value={currency} />
</label> </Grid>
<CurrencyInput class="join-item" bind:value={currency} />
</div>
{/snippet} {/snippet}
</Field> </Field>
{#if initialValues} {#if initialValues}
@@ -218,10 +217,10 @@
<p>Status*</p> <p>Status*</p>
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<select class="select select-bordered w-full" bind:value={status}> <Select bind:value={status}>
<option value="active">Active</option> <option value="active">Active</option>
<option value="sold">Sold</option> <option value="sold">Sold</option>
</select> </Select>
{/snippet} {/snippet}
</Field> </Field>
{/if} {/if}
@@ -233,14 +232,14 @@
<ImagesInput bind:value={images} /> <ImagesInput bind:value={images} />
{/snippet} {/snippet}
</Field> </Field>
</div> </Col>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back} disabled={loading}> <Button variant="ghost" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
<Button type="submit" class="btn btn-primary" disabled={loading}> <Button type="submit" variant="primary" disabled={loading}>
<Spinner {loading}>Save Listing</Spinner> <Spinner {loading}>Save Listing</Spinner>
</Button> </Button>
</ModalFooter> </ModalFooter>
+7 -7
View File
@@ -2,8 +2,8 @@
import {formatTimestamp} from "@welshman/lib" import {formatTimestamp} from "@welshman/lib"
import type {TrustedEvent} from "@welshman/util" import type {TrustedEvent} from "@welshman/util"
import {getTag, getAddress, getTagValue, getTagValues} from "@welshman/util" import {getTag, getAddress, getTagValue, getTagValues} from "@welshman/util"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components2/Link.svelte"
import CurrencySymbol from "@lib/components/CurrencySymbol.svelte" import CurrencySymbol from "@lib/components2/CurrencySymbol.svelte"
import ContentLinkBlock from "@app/components/ContentLinkBlock.svelte" import ContentLinkBlock from "@app/components/ContentLinkBlock.svelte"
import Content from "@app/components/Content.svelte" import Content from "@app/components/Content.svelte"
import ProfileLink from "@app/components/ProfileLink.svelte" import ProfileLink from "@app/components/ProfileLink.svelte"
@@ -25,20 +25,20 @@
</script> </script>
<Link <Link
class="cv col-2 card2 bg-alt w-full cursor-pointer shadow-xl" class="clay-card cl-surface-alt flex w-full cursor-pointer flex-col gap-2 p-4 sm:p-6"
href={makeClassifiedPath(url, getAddress(event))}> href={makeClassifiedPath(url, getAddress(event))}>
{#if title} {#if title}
<div class="flex w-full items-center justify-between gap-2"> <div class="flex w-full items-center justify-between gap-2">
<p class="text-xl"> <p class="cl-text text-xl">
{title} {title}
<CurrencySymbol code={currency} />{price} <CurrencySymbol code={currency} />{price}
</p> </p>
<p class="text-sm opacity-75"> <p class="cl-text-muted text-sm">
{formatTimestamp(event.created_at)} {formatTimestamp(event.created_at)}
</p> </p>
</div> </div>
{:else} {:else}
<p class="mb-3 h-0 text-xs opacity-75"> <p class="cl-text-muted mb-3 h-0 text-xs">
{formatTimestamp(event.created_at)} {formatTimestamp(event.created_at)}
</p> </p>
{/if} {/if}
@@ -49,7 +49,7 @@
{/each} {/each}
</div> </div>
<div class="flex w-full flex-col items-end justify-between gap-2 sm:flex-row"> <div class="flex w-full flex-col items-end justify-between gap-2 sm:flex-row">
<span class="whitespace-nowrap py-1 text-sm opacity-75"> <span class="cl-text-muted whitespace-nowrap py-1 text-sm">
Posted by Posted by
<ProfileLink pubkey={event.pubkey} {url} /> <ProfileLink pubkey={event.pubkey} {url} />
{#if h} {#if h}
+3 -3
View File
@@ -1,8 +1,8 @@
<script lang="ts"> <script lang="ts">
import cx from "classnames"
import type {TrustedEvent} from "@welshman/util" import type {TrustedEvent} from "@welshman/util"
import {getTagValue} from "@welshman/util" import {getTagValue} from "@welshman/util"
import {ucFirst} from "@lib/util" import {ucFirst} from "@lib/util"
import Badge from "@lib/components2/Badge.svelte"
type Props = { type Props = {
event: TrustedEvent event: TrustedEvent
@@ -14,7 +14,7 @@
</script> </script>
{#if status} {#if status}
<div class={cx("btn btn-xs rounded-full", {"btn-primary": status !== "active"})}> <Badge sm variant={status !== "active" ? "primary" : "neutral"}>
{ucFirst(status)} {ucFirst(status)}
</div> </Badge>
{/if} {/if}
+1 -1
View File
@@ -31,7 +31,7 @@
<div class="flex flex-wrap items-center justify-between gap-2"> <div class="flex flex-wrap items-center justify-between gap-2">
<div class="flex grow flex-wrap justify-end gap-2"> <div class="flex grow flex-wrap justify-end gap-2">
<ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="tooltip-left" /> <ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="cl-tip-left" />
<ThunkStatusOrDeleted {event} /> <ThunkStatusOrDeleted {event} />
{#if showActivity} {#if showActivity}
<EventActivity {url} {path} {event} /> <EventActivity {url} {path} {event} />
+8 -8
View File
@@ -5,8 +5,8 @@
import NotesMinimalistic from "@assets/icons/notes-minimalistic.svg?dataurl" import NotesMinimalistic from "@assets/icons/notes-minimalistic.svg?dataurl"
import CaseMinimalistic from "@assets/icons/case-minimalistic.svg?dataurl" import CaseMinimalistic from "@assets/icons/case-minimalistic.svg?dataurl"
import Revote from "@assets/icons/revote.svg?dataurl" import Revote from "@assets/icons/revote.svg?dataurl"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import {pushModal} from "@app/modal" import {pushModal} from "@app/modal"
import CalendarEventCreate from "@app/components/CalendarEventCreate.svelte" import CalendarEventCreate from "@app/components/CalendarEventCreate.svelte"
import ThreadCreate from "@app/components/ThreadCreate.svelte" import ThreadCreate from "@app/components/ThreadCreate.svelte"
@@ -39,33 +39,33 @@
}) })
</script> </script>
<ul class="menu whitespace-nowrap rounded-box bg-base-100 p-2 shadow-md" bind:this={ul}> <ul class="clay-card flex flex-col gap-1 whitespace-nowrap p-2" bind:this={ul}>
<li> <li>
<Button onclick={createGoal}> <Button block class="justify-start" onclick={createGoal}>
<Icon size={4} icon={StarFallMinimalistic} /> <Icon size={4} icon={StarFallMinimalistic} />
Funding Goal Funding Goal
</Button> </Button>
</li> </li>
<li> <li>
<Button onclick={createCalendarEvent}> <Button block class="justify-start" onclick={createCalendarEvent}>
<Icon size={4} icon={CalendarMinimalistic} /> <Icon size={4} icon={CalendarMinimalistic} />
Calendar Event Calendar Event
</Button> </Button>
</li> </li>
<li> <li>
<Button onclick={createClassified}> <Button block class="justify-start" onclick={createClassified}>
<Icon size={4} icon={CaseMinimalistic} /> <Icon size={4} icon={CaseMinimalistic} />
Classified Listing Classified Listing
</Button> </Button>
</li> </li>
<li> <li>
<Button onclick={createThread}> <Button block class="justify-start" onclick={createThread}>
<Icon size={4} icon={NotesMinimalistic} /> <Icon size={4} icon={NotesMinimalistic} />
Create Thread Create Thread
</Button> </Button>
</li> </li>
<li> <li>
<Button onclick={createPoll}> <Button block class="justify-start" onclick={createPoll}>
<Icon size={4} icon={Revote} /> <Icon size={4} icon={Revote} />
Ask a Question Ask a Question
</Button> </Button>
+16 -15
View File
@@ -21,10 +21,12 @@
} from "@welshman/content" } from "@welshman/content"
import type {Parsed} from "@welshman/content" import type {Parsed} from "@welshman/content"
import {preventDefault, stopPropagation} from "@lib/html" import {preventDefault, stopPropagation} from "@lib/html"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components2/Link.svelte"
import Danger from "@assets/icons/danger-triangle.svg?dataurl" import Danger from "@assets/icons/danger-triangle.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Alert from "@lib/components2/Alert.svelte"
import Row from "@lib/components2/Row.svelte"
import ContentToken from "@app/components/ContentToken.svelte" import ContentToken from "@app/components/ContentToken.svelte"
import ContentEmoji from "@app/components/ContentEmoji.svelte" import ContentEmoji from "@app/components/ContentEmoji.svelte"
import ContentEmail from "@app/components/ContentEmail.svelte" import ContentEmail from "@app/components/ContentEmail.svelte"
@@ -144,13 +146,15 @@
<div class="relative"> <div class="relative">
{#if warning} {#if warning}
<div class="card2 card2-sm bg-alt row-2"> <Alert variant="warning">
<Icon icon={Danger} /> <Row gap={2}>
<p> <Icon icon={Danger} />
This note has been flagged by the author as "{warning}".<br /> <p>
<Button class="link" onclick={ignoreWarning}>Show anyway</Button> This note has been flagged by the author as "{warning}".<br />
</p> <Button class="cl-link" onclick={ignoreWarning}>Show anyway</Button>
</div> </p>
</Row>
</Alert>
{:else} {:else}
<div <div
class="overflow-hidden text-ellipsis wrap-break-word" class="overflow-hidden text-ellipsis wrap-break-word"
@@ -204,12 +208,9 @@
</div> </div>
{#if expandBlock} {#if expandBlock}
<div class="relative z-feature -mt-6 flex justify-center py-2"> <div class="relative z-feature -mt-6 flex justify-center py-2">
<button <Button variant="secondary" onclick={stopPropagation(preventDefault(expand))}>
type="button"
class="btn btn-neutral"
onclick={stopPropagation(preventDefault(expand))}>
See more See more
</button> </Button>
</div> </div>
{/if} {/if}
{/if} {/if}
+1 -1
View File
@@ -3,7 +3,7 @@
</script> </script>
<code <code
class="w-full overflow-auto whitespace-pre rounded bg-neutral px-1 text-neutral-content" class="cl-surface-alt cl-text w-full overflow-auto whitespace-pre rounded px-1"
class:block={isBlock}> class:block={isBlock}>
{value.trim()} {value.trim()}
</code> </code>
+2 -2
View File
@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import LinkRound from "@assets/icons/link-round.svg?dataurl" import LinkRound from "@assets/icons/link-round.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components2/Link.svelte"
export let value: string export let value: string
</script> </script>
+20 -11
View File
@@ -3,7 +3,8 @@
import {isRelayUrl, getTagValue} from "@welshman/util" import {isRelayUrl, getTagValue} from "@welshman/util"
import {Capacitor} from "@capacitor/core" import {Capacitor} from "@capacitor/core"
import {preventDefault, stopPropagation} from "@lib/html" import {preventDefault, stopPropagation} from "@lib/html"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components2/Link.svelte"
import Center from "@lib/components2/Center.svelte"
import ContentLinkDetail from "@app/components/ContentLinkDetail.svelte" import ContentLinkDetail from "@app/components/ContentLinkDetail.svelte"
import ContentLinkUrl from "@app/components/ContentLinkUrl.svelte" import ContentLinkUrl from "@app/components/ContentLinkUrl.svelte"
import ContentLinkBlockImage from "@app/components/ContentLinkBlockImage.svelte" import ContentLinkBlockImage from "@app/components/ContentLinkBlockImage.svelte"
@@ -53,37 +54,45 @@
{#if isRoomOrRelay} {#if isRoomOrRelay}
<div> <div>
<ContentLinkUrl {url} class="link-content whitespace-nowrap" /> <ContentLinkUrl
{url}
class="cl-surface-alt cl-text inline-block max-w-full overflow-hidden text-ellipsis whitespace-nowrap rounded px-1" />
</div> </div>
{:else} {:else}
<Link {external} {href} class="my-2 block"> <Link {external} {href} class="my-2 block">
<div class="overflow-hidden rounded-box"> <div class="overflow-hidden" style="border-radius: var(--cl-r-card)">
{#if url.match(/\.(mov|webm|mp4)$/) || VIDEO_CONTENT_TYPES.includes(fileType)} {#if url.match(/\.(mov|webm|mp4)$/) || VIDEO_CONTENT_TYPES.includes(fileType)}
<video <video
controls controls
src={url} src={url}
poster={getVideoPoster(url)} poster={getVideoPoster(url)}
preload="metadata" preload="metadata"
class="max-h-96 rounded-box object-contain object-center"> class="max-h-96 object-contain object-center"
style="border-radius: var(--cl-r-card)">
<track kind="captions" /> <track kind="captions" />
</video> </video>
{:else if url.match(/\.(jpe?g|png|gif|webp)$/) || IMAGE_CONTENT_TYPES.includes(fileType)} {:else if url.match(/\.(jpe?g|png|gif|webp)$/) || IMAGE_CONTENT_TYPES.includes(fileType)}
<button type="button" onclick={stopPropagation(preventDefault(expand))}> <button type="button" onclick={stopPropagation(preventDefault(expand))}>
<ContentLinkBlockImage {value} {event} class="m-auto max-h-96 rounded-box" /> <ContentLinkBlockImage
{value}
{event}
class="m-auto max-h-96"
style="border-radius: var(--cl-r-card)" />
</button> </button>
{:else} {:else}
{#await loadPreview()} {#await loadPreview()}
<div class="center my-12 w-full"> <Center class="my-12 w-full">
<span class="loading loading-spinner"></span> <span class="cl-spinner"></span>
</div> </Center>
{:then preview} {:then preview}
<div class="bg-alt flex max-w-xl flex-col leading-normal"> <div class="cl-surface-alt flex max-w-xl flex-col leading-normal">
{#if preview.image && !hideImage} {#if preview.image && !hideImage}
<img <img
alt="" alt=""
onerror={onError} onerror={onError}
src={preview.image} src={preview.image}
class="bg-alt max-h-72 rounded-t-box object-contain object-center" /> class="cl-surface-alt max-h-72 object-contain object-center"
style="border-top-left-radius: var(--cl-r-card); border-top-right-radius: var(--cl-r-card)" />
{/if} {/if}
<div class="flex flex-col gap-2 p-4"> <div class="flex flex-col gap-2 p-4">
<strong class="overflow-hidden text-ellipsis whitespace-nowrap" <strong class="overflow-hidden text-ellipsis whitespace-nowrap"
@@ -92,7 +101,7 @@
</div> </div>
</div> </div>
{:catch} {:catch}
<p class="bg-alt p-12 text-center leading-normal"> <p class="cl-surface-alt p-12 text-center leading-normal">
Unable to load a preview for {url} Unable to load a preview for {url}
</p> </p>
{/await} {/await}
@@ -11,7 +11,7 @@
} from "@welshman/util" } from "@welshman/util"
import {signer} from "@welshman/app" import {signer} from "@welshman/app"
import LinkRound from "@assets/icons/link-round.svg?dataurl" import LinkRound from "@assets/icons/link-round.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
const {value, event, ...props} = $props() const {value, event, ...props} = $props()
@@ -87,7 +87,9 @@
</script> </script>
{#if hasError} {#if hasError}
<a href={url} class="link-content whitespace-nowrap"> <a
href={url}
class="cl-surface-alt inline-flex max-w-full items-center gap-1 overflow-hidden rounded px-1 whitespace-nowrap text-ellipsis">
<Icon icon={LinkRound} size={3} class="inline-block" /> <Icon icon={LinkRound} size={3} class="inline-block" />
{displayUrl(url)} {displayUrl(url)}
</a> </a>
+6 -2
View File
@@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import ContentLinkBlockImage from "@app/components/ContentLinkBlockImage.svelte" import ContentLinkBlockImage from "@app/components/ContentLinkBlockImage.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
const {value, event} = $props() const {value, event} = $props()
@@ -8,5 +8,9 @@
</script> </script>
<Button class="m-auto h-screen w-screen cursor-pointer p-4" onclick={back}> <Button class="m-auto h-screen w-screen cursor-pointer p-4" onclick={back}>
<ContentLinkBlockImage {value} {event} class="m-auto max-h-full max-w-full rounded-box" /> <ContentLinkBlockImage
{value}
{event}
class="m-auto max-h-full max-w-full"
style="border-radius: var(--cl-r-card);" />
</Button> </Button>
+5 -3
View File
@@ -3,7 +3,7 @@
import {getTagValue} from "@welshman/util" import {getTagValue} from "@welshman/util"
import {preventDefault, stopPropagation} from "@lib/html" import {preventDefault, stopPropagation} from "@lib/html"
import LinkRound from "@assets/icons/link-round.svg?dataurl" import LinkRound from "@assets/icons/link-round.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import ContentLinkDetail from "@app/components/ContentLinkDetail.svelte" import ContentLinkDetail from "@app/components/ContentLinkDetail.svelte"
import ContentLinkUrl from "@app/components/ContentLinkUrl.svelte" import ContentLinkUrl from "@app/components/ContentLinkUrl.svelte"
import {pushModal} from "@app/modal" import {pushModal} from "@app/modal"
@@ -21,11 +21,13 @@
<!-- Use a real link so people can copy the href --> <!-- Use a real link so people can copy the href -->
<a <a
href={url} href={url}
class="link-content whitespace-nowrap" class="cl-surface-alt inline-flex max-w-full items-center gap-1 overflow-hidden rounded px-1 whitespace-nowrap text-ellipsis"
onclick={stopPropagation(preventDefault(expand))}> onclick={stopPropagation(preventDefault(expand))}>
<Icon icon={LinkRound} size={3} class="inline-block" /> <Icon icon={LinkRound} size={3} class="inline-block" />
{displayUrl(url)} {displayUrl(url)}
</a> </a>
{:else} {:else}
<ContentLinkUrl {url} class="link-content whitespace-nowrap" /> <ContentLinkUrl
{url}
class="cl-surface-alt inline-flex max-w-full items-center gap-1 overflow-hidden rounded px-1 whitespace-nowrap text-ellipsis" />
{/if} {/if}
+4 -4
View File
@@ -2,8 +2,8 @@
import {call, displayUrl} from "@welshman/lib" import {call, displayUrl} from "@welshman/lib"
import {displayRelayUrl, isRelayUrl, normalizeRelayUrl} from "@welshman/util" import {displayRelayUrl, isRelayUrl, normalizeRelayUrl} from "@welshman/util"
import LinkRound from "@assets/icons/link-round.svg?dataurl" import LinkRound from "@assets/icons/link-round.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components2/Link.svelte"
import {PLATFORM_URL} from "@app/env" import {PLATFORM_URL} from "@app/env"
import {displayRoom, isRoomId, splitRoomId} from "@app/groups" import {displayRoom, isRoomId, splitRoomId} from "@app/groups"
import {makeRoomPath, makeSpacePath} from "@app/routes" import {makeRoomPath, makeSpacePath} from "@app/routes"
@@ -49,10 +49,10 @@
<Link {external} {href} class={className}> <Link {external} {href} class={className}>
{#if roomReference} {#if roomReference}
~<span class="text-primary">{displayRelayUrl(roomReference.url)}</span> / ~<span class="cl-text-primary">{displayRelayUrl(roomReference.url)}</span> /
{displayRoom(roomReference.url, roomReference.h)} {displayRoom(roomReference.url, roomReference.h)}
{:else if relayReference} {:else if relayReference}
<span class="text-primary">{displayRelayUrl(relayReference)}</span> <span class="cl-text-primary">{displayRelayUrl(relayReference)}</span>
{:else} {:else}
<Icon icon={LinkRound} size={3} class="inline-block" /> <Icon icon={LinkRound} size={3} class="inline-block" />
{displayUrl(url)} {displayUrl(url)}
+2 -2
View File
@@ -2,7 +2,7 @@
import {removeUndefined} from "@welshman/lib" import {removeUndefined} from "@welshman/lib"
import type {ProfilePointer} from "@welshman/content" import type {ProfilePointer} from "@welshman/content"
import {deriveProfileDisplay} from "@welshman/app" import {deriveProfileDisplay} from "@welshman/app"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import ProfileDetail from "@app/components/ProfileDetail.svelte" import ProfileDetail from "@app/components/ProfileDetail.svelte"
import {pushModal} from "@app/modal" import {pushModal} from "@app/modal"
@@ -18,6 +18,6 @@
const openProfile = () => pushModal(ProfileDetail, {pubkey: value.pubkey, url}) const openProfile = () => pushModal(ProfileDetail, {pubkey: value.pubkey, url})
</script> </script>
<Button onclick={openProfile} class="link-content"> <Button onclick={openProfile} class="cl-link">
@{$display} @{$display}
</Button> </Button>
+7 -6
View File
@@ -19,10 +19,11 @@
isNewline, isNewline,
} from "@welshman/content" } from "@welshman/content"
import type {Parsed} from "@welshman/content" import type {Parsed} from "@welshman/content"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components2/Link.svelte"
import Danger from "@assets/icons/danger-triangle.svg?dataurl" import Danger from "@assets/icons/danger-triangle.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Alert from "@lib/components2/Alert.svelte"
import ContentToken from "@app/components/ContentToken.svelte" import ContentToken from "@app/components/ContentToken.svelte"
import ContentEmoji from "@app/components/ContentEmoji.svelte" import ContentEmoji from "@app/components/ContentEmoji.svelte"
import ContentEmail from "@app/components/ContentEmail.svelte" import ContentEmail from "@app/components/ContentEmail.svelte"
@@ -96,13 +97,13 @@
<div class="relative"> <div class="relative">
{#if warning} {#if warning}
<div class="card2 card2-sm bg-alt row-2"> <Alert variant="warning" class="items-center">
<Icon icon={Danger} /> <Icon icon={Danger} />
<p> <p>
This note has been flagged by the author as "{warning}".<br /> This note has been flagged by the author as "{warning}".<br />
<Button class="link" onclick={ignoreWarning}>Show anyway</Button> <Button class="cl-link" onclick={ignoreWarning}>Show anyway</Button>
</p> </p>
</div> </Alert>
{:else} {:else}
<div class="overflow-hidden text-ellipsis wrap-break-word"> <div class="overflow-hidden text-ellipsis wrap-break-word">
{#each shortContent as parsed, i} {#each shortContent as parsed, i}
+10 -8
View File
@@ -3,8 +3,8 @@
import {Router} from "@welshman/router" import {Router} from "@welshman/router"
import type {TrustedEvent} from "@welshman/util" import type {TrustedEvent} from "@welshman/util"
import {Address, MESSAGE} from "@welshman/util" import {Address, MESSAGE} from "@welshman/util"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components2/Spinner.svelte"
import NoteCard from "@app/components/NoteCard.svelte" import NoteCard from "@app/components/NoteCard.svelte"
import NoteContent from "@app/components/NoteContent.svelte" import NoteContent from "@app/components/NoteContent.svelte"
import NoteContentMinimal from "@app/components/NoteContentMinimal.svelte" import NoteContentMinimal from "@app/components/NoteContentMinimal.svelte"
@@ -48,17 +48,19 @@
<NoteContent {url} event={$quote} /> <NoteContent {url} event={$quote} />
{:else if $quote.kind === MESSAGE} {:else if $quote.kind === MESSAGE}
<div <div
class="border-l-2 border-solid border-l-primary py-1 pl-2 opacity-90" class="cl-surface-alt py-1 pl-2 opacity-90"
style="background-color: color-mix(in srgb, var(--color-primary) 10%, var(--color-base-300) 90%);"> style="border-left: 2px solid var(--cl-primary);">
<NoteContentMinimal trimParent {url} event={$quote} /> <NoteContentMinimal trimParent {url} event={$quote} />
</div> </div>
{:else} {:else}
<NoteCard noShadow event={$quote} {url} class="bg-alt rounded-box p-4"> <div class="cl-surface-alt overflow-hidden" style="border-radius: var(--cl-r-card);">
<NoteContentMinimal {url} event={$quote} /> <NoteCard noShadow event={$quote} {url} class="p-4">
</NoteCard> <NoteContentMinimal {url} event={$quote} />
</NoteCard>
</div>
{/if} {/if}
{:else} {:else}
<div class="rounded-box p-4"> <div class="cl-surface-alt p-4" style="border-radius: var(--cl-r-card);">
<Spinner loading>Loading event...</Spinner> <Spinner loading>Loading event...</Spinner>
</div> </div>
{/if} {/if}
+3 -3
View File
@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import Bolt from "@assets/icons/bolt.svg?dataurl" import Bolt from "@assets/icons/bolt.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import {clip} from "@app/toast" import {clip} from "@app/toast"
const {value} = $props() const {value} = $props()
@@ -9,7 +9,7 @@
const copy = () => clip(value) const copy = () => clip(value)
</script> </script>
<Button onclick={copy} class="link-content"> <Button onclick={copy} variant="secondary" size="sm" class="max-w-full truncate align-middle">
<Icon icon={Bolt} size={3} class="inline-block translate-y-px" /> <Icon icon={Bolt} size={3} class="inline-block translate-y-px" />
{value.slice(0, 16)}... {value.slice(0, 16)}...
</Button> </Button>
+4 -2
View File
@@ -1,7 +1,9 @@
<script lang="ts"> <script lang="ts">
import Badge from "@lib/components2/Badge.svelte"
const {value} = $props() const {value} = $props()
</script> </script>
<span class="link-content"> <Badge variant="neutral">
#{value} #{value}
</span> </Badge>
+6 -10
View File
@@ -6,11 +6,11 @@
import {preventDefault} from "@lib/html" import {preventDefault} from "@lib/html"
import {createSearch} from "@welshman/app" import {createSearch} from "@welshman/app"
import {currencyOptions, displayCurrency} from "@lib/currency" import {currencyOptions, displayCurrency} from "@lib/currency"
import Suggestions from "@lib/components/Suggestions.svelte" import Suggestions from "@lib/components2/Suggestions.svelte"
import CurrencySuggestion from "@app/components/CurrencySuggestion.svelte" import CurrencySuggestion from "@app/components/CurrencySuggestion.svelte"
import AltArrowDown from "@assets/icons/alt-arrow-down.svg?dataurl" import AltArrowDown from "@assets/icons/alt-arrow-down.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Tippy from "@lib/components/Tippy.svelte" import Tippy from "@lib/components2/Tippy.svelte"
interface Props { interface Props {
value: string value: string
@@ -66,22 +66,18 @@
</script> </script>
<button <button
class={cx( class={cx(props.class, "input-cl input-cl-group cursor-pointer", {"cl-surface-alt": currency})}
props.class,
{"bg-base-200": currency},
"input input-bordered flex items-center gap-2 cursor-pointer",
)}
bind:this={wrapper} bind:this={wrapper}
onfocus={preventDefault(clearAndFocus)} onfocus={preventDefault(clearAndFocus)}
onclick={preventDefault(clearAndFocus)}> onclick={preventDefault(clearAndFocus)}>
<Icon icon={AltArrowDown} /> <Icon icon={AltArrowDown} />
{#if currency} {#if currency}
<span class="text-sm ellipsize whitespace-nowrap"> <span class="overflow-hidden text-ellipsis whitespace-nowrap text-sm">
{displayCurrency(currency)} {displayCurrency(currency)}
</span> </span>
{:else} {:else}
<!-- svelte-ignore a11y_autofocus --> <!-- svelte-ignore a11y_autofocus -->
<input {autofocus} class="grow" type="text" bind:value={$term} onkeydown={onKeyDown} /> <input {autofocus} class="input-cl-bare grow" type="text" bind:value={$term} onkeydown={onKeyDown} />
{/if} {/if}
<Tippy <Tippy
bind:popover bind:popover
+10 -9
View File
@@ -6,11 +6,12 @@
import Bolt from "@assets/icons/bolt.svg?dataurl" import Bolt from "@assets/icons/bolt.svg?dataurl"
import SmileCircle from "@assets/icons/smile-circle.svg?dataurl" import SmileCircle from "@assets/icons/smile-circle.svg?dataurl"
import MenuDots from "@assets/icons/menu-dots.svg?dataurl" import MenuDots from "@assets/icons/menu-dots.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Tippy from "@lib/components/Tippy.svelte" import Tippy from "@lib/components2/Tippy.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Row from "@lib/components2/Row.svelte"
import ZapButton from "@app/components/ZapButton.svelte" import ZapButton from "@app/components/ZapButton.svelte"
import EmojiButton from "@lib/components/EmojiButton.svelte" import EmojiButton from "@lib/components2/EmojiButton.svelte"
import EventMenu from "@app/components/EventMenu.svelte" import EventMenu from "@app/components/EventMenu.svelte"
import {ENABLE_ZAPS} from "@app/env" import {ENABLE_ZAPS} from "@app/env"
import {publishReaction} from "@app/reactions" import {publishReaction} from "@app/reactions"
@@ -43,13 +44,13 @@
let popover: Instance | undefined = $state() let popover: Instance | undefined = $state()
</script> </script>
<div class="join items-center rounded-full"> <Row gap={1} class="cl-surface-alt cl-border rounded-full px-1 py-1">
{#if ENABLE_ZAPS && !hideZap} {#if ENABLE_ZAPS && !hideZap}
<ZapButton {url} {event} class="btn join-item btn-neutral btn-xs"> <ZapButton {url} {event} class="btn-cl-sm">
<Icon icon={Bolt} size={4} /> <Icon icon={Bolt} size={4} />
</ZapButton> </ZapButton>
{/if} {/if}
<EmojiButton {onEmoji} class="btn join-item btn-neutral btn-xs"> <EmojiButton {onEmoji} class="btn-cl-sm">
<Icon icon={SmileCircle} size={4} /> <Icon icon={SmileCircle} size={4} />
</EmojiButton> </EmojiButton>
<Tippy <Tippy
@@ -58,8 +59,8 @@
component={EventMenu} component={EventMenu}
props={{url, noun, event, customActions, onClick: hidePopover}} props={{url, noun, event, customActions, onClick: hidePopover}}
params={{trigger: "manual", interactive: true}}> params={{trigger: "manual", interactive: true}}>
<Button class="btn join-item btn-neutral btn-xs" onclick={showPopover}> <Button class="btn-cl-sm" onclick={showPopover}>
<Icon icon={MenuDots} size={4} /> <Icon icon={MenuDots} size={4} />
</Button> </Button>
</Tippy> </Tippy>
</div> </Row>
+8 -7
View File
@@ -8,7 +8,8 @@
import {repository} from "@welshman/app" import {repository} from "@welshman/app"
import {deriveChecked} from "@app/notifications" import {deriveChecked} from "@app/notifications"
import Reply from "@assets/icons/reply-2.svg?dataurl" import Reply from "@assets/icons/reply-2.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Badge from "@lib/components2/Badge.svelte"
const {url, path, event}: {url: string; path: string; event: TrustedEvent} = $props() const {url, path, event}: {url: string; path: string; event: TrustedEvent} = $props()
@@ -22,13 +23,13 @@
}) })
</script> </script>
<div class="flex-inline btn btn-neutral btn-xs gap-1 rounded-full"> <Badge sm>
<Icon icon={Reply} /> <Icon icon={Reply} size={4} />
<span>{$replies.length} {$replies.length === 1 ? "reply" : "replies"}</span> <span>{$replies.length} {$replies.length === 1 ? "reply" : "replies"}</span>
</div> </Badge>
<div class="btn btn-neutral btn-xs relative rounded-full"> <Badge sm>
{#if gt(lastActive, $checked)} {#if gt(lastActive, $checked)}
<div class="h-2 w-2 rounded-full bg-primary"></div> <div class="h-2 w-2 rounded-full" style="background-color: var(--cl-primary);"></div>
{/if} {/if}
Active {formatTimestampRelative(lastActive)} Active {formatTimestampRelative(lastActive)}
</div> </Badge>
+1 -1
View File
@@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import type {TrustedEvent} from "@welshman/util" import type {TrustedEvent} from "@welshman/util"
import Confirm from "@lib/components/Confirm.svelte" import Confirm from "@lib/components2/Confirm.svelte"
import {publishDelete} from "@app/deletes" import {publishDelete} from "@app/deletes"
import {canEnforceNip70} from "@app/relays" import {canEnforceNip70} from "@app/relays"
import {clearModals} from "@app/modal" import {clearModals} from "@app/modal"
+22 -20
View File
@@ -8,15 +8,16 @@
import FileText from "@assets/icons/file-text.svg?dataurl" import FileText from "@assets/icons/file-text.svg?dataurl"
import Copy from "@assets/icons/copy.svg?dataurl" import Copy from "@assets/icons/copy.svg?dataurl"
import UserCircle from "@assets/icons/user-circle.svg?dataurl" import UserCircle from "@assets/icons/user-circle.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import FieldInline from "@lib/components/FieldInline.svelte" import FieldInline from "@lib/components2/FieldInline.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Modal from "@lib/components/Modal.svelte" import Badge from "@lib/components2/Badge.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalFooter from "@lib/components2/ModalFooter.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import {clip} from "@app/toast" import {clip} from "@app/toast"
type Props = { type Props = {
@@ -60,13 +61,13 @@
<p>Event Link</p> <p>Event Link</p>
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<label class="input input-bordered flex w-full items-center gap-2"> <div class="input-cl input-cl-group w-full">
<Icon icon={FileText} /> <Icon icon={FileText} />
<input type="text" class="ellipsize min-w-0 grow" value={nevent1} /> <input type="text" class="input-cl-bare overflow-hidden text-ellipsis" value={nevent1} />
<Button onclick={copyLink} class="flex items-center"> <Button onclick={copyLink} class="flex items-center">
<Icon icon={Copy} /> <Icon icon={Copy} />
</Button> </Button>
</label> </div>
{/snippet} {/snippet}
</FieldInline> </FieldInline>
<FieldInline> <FieldInline>
@@ -74,13 +75,13 @@
<p>Author Pubkey</p> <p>Author Pubkey</p>
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<label class="input input-bordered flex w-full items-center gap-2"> <div class="input-cl input-cl-group w-full">
<Icon icon={UserCircle} /> <Icon icon={UserCircle} />
<input type="text" class="ellipsize min-w-0 grow" value={npub1} /> <input type="text" class="input-cl-bare overflow-hidden text-ellipsis" value={npub1} />
<Button onclick={copyPubkey} class="flex items-center"> <Button onclick={copyPubkey} class="flex items-center">
<Icon icon={Copy} /> <Icon icon={Copy} />
</Button> </Button>
</label> </div>
{/snippet} {/snippet}
</FieldInline> </FieldInline>
{#if !url && seenOn.size > 0} {#if !url && seenOn.size > 0}
@@ -91,24 +92,25 @@
{#snippet input()} {#snippet input()}
<div class="flex flex-wrap gap-2"> <div class="flex flex-wrap gap-2">
{#each seenOn as url, i (url)} {#each seenOn as url, i (url)}
<span class="bg-alt badge flex gap-1"> <Badge>
{displayRelayUrl(url)} {displayRelayUrl(url)}
</span> </Badge>
{/each} {/each}
</div> </div>
{/snippet} {/snippet}
</FieldInline> </FieldInline>
{/if} {/if}
<div class="relative"> <div class="relative">
<pre class="card2 card2-sm bg-alt overflow-auto text-xs"><code>{json}</code></pre> <pre
class="cl-surface-alt cl-border overflow-auto rounded-2xl p-4 text-xs"><code>{json}</code></pre>
<p class="absolute right-2 top-2 flex grow items-center justify-between"> <p class="absolute right-2 top-2 flex grow items-center justify-between">
<Button onclick={copyJson} class="btn btn-neutral btn-sm flex items-center"> <Button variant="secondary" size="sm" onclick={copyJson} class="flex items-center">
<Icon icon={Copy} /> Copy <Icon icon={Copy} /> Copy
</Button> </Button>
</p> </p>
</div> </div>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-primary grow" onclick={() => history.back()}>Got it</Button> <Button variant="primary" class="grow" onclick={() => history.back()}>Got it</Button>
</ModalFooter> </ModalFooter>
</Modal> </Modal>
+24 -34
View File
@@ -10,9 +10,9 @@
import TrashBin2 from "@assets/icons/trash-bin-2.svg?dataurl" import TrashBin2 from "@assets/icons/trash-bin-2.svg?dataurl"
import Danger from "@assets/icons/danger.svg?dataurl" import Danger from "@assets/icons/danger.svg?dataurl"
import {setKey} from "@lib/implicit" import {setKey} from "@lib/implicit"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Confirm from "@lib/components/Confirm.svelte" import Confirm from "@lib/components2/Confirm.svelte"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import EventInfo from "@app/components/EventInfo.svelte" import EventInfo from "@app/components/EventInfo.svelte"
import Report from "@app/components/Report.svelte" import Report from "@app/components/Report.svelte"
import EventShare from "@app/components/EventShare.svelte" import EventShare from "@app/components/EventShare.svelte"
@@ -78,43 +78,33 @@
}) })
</script> </script>
<ul class="menu whitespace-nowrap rounded-box bg-base-100 p-2 shadow-md" bind:this={ul}> <div class="clay-card flex flex-col gap-1 whitespace-nowrap p-2" bind:this={ul}>
{#if isRoot} {#if isRoot}
<li> <Button block onclick={share}>
<Button onclick={share}> <Icon size={4} icon={ShareCircle} />
<Icon size={4} icon={ShareCircle} /> Share to Chat
Share to Chat
</Button>
</li>
{/if}
<li>
<Button onclick={showInfo}>
<Icon size={4} icon={Code2} />
{noun} Details
</Button> </Button>
</li> {/if}
<Button block onclick={showInfo}>
<Icon size={4} icon={Code2} />
{noun} Details
</Button>
{@render customActions?.()} {@render customActions?.()}
{#if event.pubkey === $pubkey} {#if event.pubkey === $pubkey}
<li> <Button block variant="danger" onclick={showDelete}>
<Button onclick={showDelete} class="text-error"> <Icon size={4} icon={TrashBin2} />
Delete {noun}
</Button>
{:else}
<Button block variant="danger" onclick={report}>
<Icon size={4} icon={Danger} />
Report Content
</Button>
{#if $userIsAdmin}
<Button block variant="danger" onclick={showAdminDelete}>
<Icon size={4} icon={TrashBin2} /> <Icon size={4} icon={TrashBin2} />
Delete {noun} Delete {noun}
</Button> </Button>
</li>
{:else}
<li>
<Button class="text-error" onclick={report}>
<Icon size={4} icon={Danger} />
Report Content
</Button>
</li>
{#if $userIsAdmin}
<li>
<Button class="text-error" onclick={showAdminDelete}>
<Icon size={4} icon={TrashBin2} />
Delete {noun}
</Button>
</li>
{/if} {/if}
{/if} {/if}
</ul> </div>
+8 -7
View File
@@ -5,8 +5,8 @@
import {isMobile, preventDefault} from "@lib/html" import {isMobile, preventDefault} from "@lib/html"
import {fly} from "@lib/transition" import {fly} from "@lib/transition"
import Paperclip from "@assets/icons/paperclip-2.svg?dataurl" import Paperclip from "@assets/icons/paperclip-2.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import EditorContent from "@app/editor/EditorContent.svelte" import EditorContent from "@app/editor/EditorContent.svelte"
import ChatComposeParent from "@app/components/ChatComposeParent.svelte" import ChatComposeParent from "@app/components/ChatComposeParent.svelte"
import {publishComment} from "@app/comments" import {publishComment} from "@app/comments"
@@ -101,7 +101,7 @@
bind:this={form} bind:this={form}
onsubmit={preventDefault(submit)} onsubmit={preventDefault(submit)}
class="left-content bottom-sai right-sai fixed z-feature mb-14 md:mb-0 w-full md:w-auto pr-2"> class="left-content bottom-sai right-sai fixed z-feature mb-14 md:mb-0 w-full md:w-auto pr-2">
<div class="card2 mx-2 my-2 bg-alt shadow-md"> <div class="clay-card mx-2 my-2 p-4">
{#if parent} {#if parent}
<ChatComposeParent event={parent} clear={() => onClearParent?.()} verb="Replying to" /> <ChatComposeParent event={parent} clear={() => onClearParent?.()} verb="Replying to" />
{/if} {/if}
@@ -111,18 +111,19 @@
</div> </div>
<Button <Button
data-tip="Add an image" data-tip="Add an image"
class="tooltip tooltip-left absolute bottom-1 right-2" circle
class="absolute bottom-1 right-2"
onclick={selectFiles}> onclick={selectFiles}>
{#if $uploading} {#if $uploading}
<span class="loading loading-spinner loading-xs"></span> <span class="cl-spinner"></span>
{:else} {:else}
<Icon icon={Paperclip} size={3} /> <Icon icon={Paperclip} size={3} />
{/if} {/if}
</Button> </Button>
</div> </div>
<div class="flex justify-between pt-3"> <div class="flex justify-between pt-3">
<Button class="btn btn-link" onclick={onClose}>Cancel</Button> <Button onclick={onClose}>Cancel</Button>
<Button type="submit" class="btn btn-primary">Post Reply</Button> <Button type="submit" variant="primary">Post Reply</Button>
</div> </div>
</div> </div>
</form> </form>
+13 -16
View File
@@ -5,14 +5,14 @@
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import {setKey} from "@lib/implicit" import {setKey} from "@lib/implicit"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components2/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import RoomName from "@app/components/RoomName.svelte" import RoomName from "@app/components/RoomName.svelte"
import {roomsByUrl} from "@app/groups" import {roomsByUrl} from "@app/groups"
import {makeRoomPath} from "@app/routes" import {makeRoomPath} from "@app/routes"
@@ -41,23 +41,20 @@
</ModalHeader> </ModalHeader>
<div class="grid grid-cols-3 gap-2"> <div class="grid grid-cols-3 gap-2">
{#each $roomsByUrl.get(url) || [] as room (room.h)} {#each $roomsByUrl.get(url) || [] as room (room.h)}
<button <Button
type="button" variant={selection === room.h ? "primary" : "secondary"}
class="btn"
class:btn-neutral={selection !== room.h}
class:btn-primary={selection === room.h}
onclick={() => toggleRoom(room.h)}> onclick={() => toggleRoom(room.h)}>
#<RoomName {...room} /> #<RoomName {...room} />
</button> </Button>
{/each} {/each}
</div> </div>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
<Button type="submit" class="btn btn-primary" disabled={!selection}> <Button type="submit" variant="primary" disabled={!selection}>
Share {noun} Share {noun}
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
+3 -3
View File
@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import type {TrustedEvent, EventContent} from "@welshman/util" import type {TrustedEvent, EventContent} from "@welshman/util"
import {getTagValue} from "@welshman/util" import {getTagValue} from "@welshman/util"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components2/Link.svelte"
import ReactionSummary from "@app/components/ReactionSummary.svelte" import ReactionSummary from "@app/components/ReactionSummary.svelte"
import ThunkStatusOrDeleted from "@app/components/ThunkStatusOrDeleted.svelte" import ThunkStatusOrDeleted from "@app/components/ThunkStatusOrDeleted.svelte"
import EventActivity from "@app/components/EventActivity.svelte" import EventActivity from "@app/components/EventActivity.svelte"
@@ -34,11 +34,11 @@
<div class="flex grow flex-wrap justify-end gap-2"> <div class="flex grow flex-wrap justify-end gap-2">
{#if h && showRoom} {#if h && showRoom}
<Link href={makeSpacePath(url, h)} class="btn btn-neutral btn-xs rounded-full"> <Link href={makeSpacePath(url, h)} class="badge-cl badge-cl-neutral badge-cl-sm">
Posted in #<RoomName {h} {url} /> Posted in #<RoomName {h} {url} />
</Link> </Link>
{/if} {/if}
<ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="tooltip-left" /> <ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="cl-tip-left" />
<ThunkStatusOrDeleted {event} /> <ThunkStatusOrDeleted {event} />
{#if showActivity} {#if showActivity}
<EventActivity {url} {path} {event} /> <EventActivity {url} {path} {event} />
+22 -22
View File
@@ -6,17 +6,17 @@
import Paperclip from "@assets/icons/paperclip-2.svg?dataurl" import Paperclip from "@assets/icons/paperclip-2.svg?dataurl"
import Bolt from "@assets/icons/bolt.svg?dataurl" import Bolt from "@assets/icons/bolt.svg?dataurl"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Field from "@lib/components/Field.svelte" import Field from "@lib/components2/Field.svelte"
import FieldInline from "@lib/components/FieldInline.svelte" import FieldInline from "@lib/components2/FieldInline.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components2/Spinner.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components2/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import EditorContent from "@app/editor/EditorContent.svelte" import EditorContent from "@app/editor/EditorContent.svelte"
import {pushToast} from "@app/toast" import {pushToast} from "@app/toast"
import {PROTECTED, publishRoomQuote} from "@app/groups" import {PROTECTED, publishRoomQuote} from "@app/groups"
@@ -145,18 +145,17 @@
<ModalTitle>Create a Funding Goal</ModalTitle> <ModalTitle>Create a Funding Goal</ModalTitle>
<ModalSubtitle>Request contributions for your fundraiser.</ModalSubtitle> <ModalSubtitle>Request contributions for your fundraiser.</ModalSubtitle>
</ModalHeader> </ModalHeader>
<div class="col-8 relative"> <div class="relative flex flex-col gap-8">
<Field> <Field>
{#snippet label()} {#snippet label()}
<p>Title*</p> <p>Title*</p>
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<label class="input input-bordered flex w-full items-center gap-2"> <label class="input-cl input-cl-group">
<!-- svelte-ignore a11y_autofocus --> <!-- svelte-ignore a11y_autofocus -->
<input <input
autofocus={!isMobile} autofocus={!isMobile}
bind:value={title} bind:value={title}
class="grow"
type="text" type="text"
placeholder="What do funds go towards?" /> placeholder="What do funds go towards?" />
</label> </label>
@@ -175,11 +174,11 @@
</Field> </Field>
<Button <Button
data-tip="Add an image" data-tip="Add an image"
class="tooltip tooltip-left absolute bottom-1 right-2" class="absolute bottom-1 right-2"
onclick={selectFiles} onclick={selectFiles}
disabled={loading}> disabled={loading}>
{#if $uploading} {#if $uploading}
<span class="loading loading-spinner loading-xs"></span> <span class="cl-spinner"></span>
{:else} {:else}
<Icon icon={Paperclip} size={3} /> <Icon icon={Paperclip} size={3} />
{/if} {/if}
@@ -192,16 +191,17 @@
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<div class="flex grow justify-end"> <div class="flex grow justify-end">
<label class="input input-bordered flex w-auto items-center gap-2"> <label class="input-cl input-cl-group w-auto">
<Icon icon={Bolt} /> <Icon icon={Bolt} />
<input bind:value={amount} type="number" class="w-28 grow" /> <input bind:value={amount} type="number" class="input-cl-bare w-28" />
<p class="shrink-0 opacity-50">sats</p> <p class="cl-text-subtle shrink-0">sats</p>
</label> </label>
</div> </div>
{/snippet} {/snippet}
</FieldInline> </FieldInline>
<input <input
class="range range-primary -mt-2 w-full" class="-mt-2 w-full"
style="accent-color: var(--cl-primary);"
type="range" type="range"
min="1000" min="1000"
max="100000" max="100000"
@@ -211,11 +211,11 @@
</div> </div>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back} disabled={loading}> <Button variant="ghost" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
<Button type="submit" class="btn btn-primary" disabled={$uploading || loading}> <Button type="submit" variant="primary" disabled={$uploading || loading}>
<Spinner {loading}>Create Goal</Spinner> <Spinner {loading}>Create Goal</Spinner>
</Button> </Button>
</ModalFooter> </ModalFooter>
+26 -21
View File
@@ -1,7 +1,9 @@
<script lang="ts"> <script lang="ts">
import type {TrustedEvent} from "@welshman/util" import type {TrustedEvent} from "@welshman/util"
import {getTagValue} from "@welshman/util" import {getTagValue} from "@welshman/util"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components2/Link.svelte"
import Col from "@lib/components2/Col.svelte"
import Text from "@lib/components2/Text.svelte"
import Content from "@app/components/Content.svelte" import Content from "@app/components/Content.svelte"
import ProfileLink from "@app/components/ProfileLink.svelte" import ProfileLink from "@app/components/ProfileLink.svelte"
import GoalActions from "@app/components/GoalActions.svelte" import GoalActions from "@app/components/GoalActions.svelte"
@@ -20,24 +22,27 @@
const h = getTagValue("h", event.tags) const h = getTagValue("h", event.tags)
</script> </script>
<Link <Link class="w-full" href={makeGoalPath(url, event.id)}>
class="cv col-2 card2 bg-alt w-full cursor-pointer shadow-md" <Col
href={makeGoalPath(url, event.id)}> gap={2}
<p class="text-2xl">{event.content}</p> class="clay-card clay-card-interactive cl-surface-alt w-full p-4 sm:p-6"
<Content style="content-visibility: auto;">
event={{content: summary, tags: event.tags}} <p class="text-2xl">{event.content}</p>
{url} <Content
expandMode="inline" event={{content: summary, tags: event.tags}}
minLength={50} {url}
maxLength={300} /> expandMode="inline"
<GoalSummary {url} {event} /> minLength={50}
<div class="flex w-full flex-col items-end justify-between gap-2 sm:flex-row"> maxLength={300} />
<span class="whitespace-nowrap py-1 text-sm opacity-75"> <GoalSummary {url} {event} />
Posted by <ProfileLink pubkey={event.pubkey} {url} /> <div class="flex w-full flex-col items-end justify-between gap-2 sm:flex-row">
{#if h} <Text size="sm" muted class="whitespace-nowrap py-1">
in <RoomLink {url} {h} /> Posted by <ProfileLink pubkey={event.pubkey} {url} />
{/if} {#if h}
</span> in <RoomLink {url} {h} />
<GoalActions showActivity {url} {event} /> {/if}
</div> </Text>
<GoalActions showActivity {url} {event} />
</div>
</Col>
</Link> </Link>
+16 -19
View File
@@ -5,7 +5,11 @@
import {deriveItemsByKey, deriveArray} from "@welshman/store" import {deriveItemsByKey, deriveArray} from "@welshman/store"
import {repository, getValidZap} from "@welshman/app" import {repository, getValidZap} from "@welshman/app"
import Bolt from "@assets/icons/bolt.svg?dataurl" import Bolt from "@assets/icons/bolt.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Stat from "@lib/components2/Stat.svelte"
import Row from "@lib/components2/Row.svelte"
import Col from "@lib/components2/Col.svelte"
import Progress from "@lib/components2/Progress.svelte"
import ZapButton from "@app/components/ZapButton.svelte" import ZapButton from "@app/components/ZapButton.svelte"
type Props = { type Props = {
@@ -31,24 +35,17 @@
const daysOld = Math.ceil((now() - event.created_at) / DAY) const daysOld = Math.ceil((now() - event.created_at) / DAY)
</script> </script>
<div class="flex flex-col gap-8 {props.class}"> <Col gap={8} class={props.class}>
<div class="flex gap-8"> <Row gap={8} class="items-start">
<div> <Stat value="{zapAmount} sats" label="funded of {goalAmount} sats" gradient />
<p class="text-xl text-primary">{zapAmount} sats</p> <Stat
<p class="text-sm opacity-75">funded of {goalAmount} sats</p> value={contributorsCount}
</div> label={contributorsCount === 1 ? "contributor" : "contributors"} />
<div> <Stat value={daysOld} label="{daysOld === 1 ? 'day' : 'days'} old" />
<p class="text-xl">{contributorsCount}</p> </Row>
<p class="text-sm opacity-75">{contributorsCount === 1 ? "contributor" : "contributors"}</p> <Progress value={zapAmount} max={goalAmount} />
</div> <ZapButton {url} {event} class="btn-cl btn-cl-primary lg:m-auto lg:px-20">
<div>
<p class="text-xl">{daysOld}</p>
<p class="text-sm opacity-75">{daysOld === 1 ? "day" : "days"} old</p>
</div>
</div>
<progress class="progress progress-primary" value={zapAmount} max={goalAmount}></progress>
<ZapButton {url} {event} class="btn btn-primary lg:m-auto lg:px-20">
<Icon icon={Bolt} /> <Icon icon={Bolt} />
Contribute to this goal Contribute to this goal
</ZapButton> </ZapButton>
</div> </Col>
+17 -5
View File
@@ -1,6 +1,18 @@
<style>
.icon-tile {
color: var(--cl-text);
border-radius: var(--cl-r-icon);
transition: all 0.2s ease;
}
.icon-tile:hover {
background: var(--cl-primary);
color: var(--cl-primary-content);
}
</style>
<script lang="ts"> <script lang="ts">
import {createSearch} from "@welshman/app" import {createSearch} from "@welshman/app"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Magnifier from "@assets/icons/magnifier.svg?dataurl" import Magnifier from "@assets/icons/magnifier.svg?dataurl"
const iconModules = import.meta.glob("@assets/icons/*.svg", { const iconModules = import.meta.glob("@assets/icons/*.svg", {
@@ -43,9 +55,9 @@
} }
</script> </script>
<label class="input input-bordered flex w-full items-center gap-2"> <label class="input-cl input-cl-group">
<Icon icon={Magnifier} /> <Icon icon={Magnifier} />
<input bind:value={searchTerm} class="grow" type="text" placeholder="Search icons..." /> <input bind:value={searchTerm} class="input-cl-bare" type="text" placeholder="Search icons..." />
</label> </label>
<div class="mt-2 max-h-80 overflow-y-auto"> <div class="mt-2 max-h-80 overflow-y-auto">
<div class="grid grid-cols-8 gap-2 p-2"> <div class="grid grid-cols-8 gap-2 p-2">
@@ -53,9 +65,9 @@
<button <button
type="button" type="button"
title={icon.name} title={icon.name}
class="flex aspect-square items-center justify-center rounded-box transition-colors hover:bg-primary hover:text-primary-content" class="icon-tile flex aspect-square items-center justify-center"
onclick={() => handleSelect(icon.url)}> onclick={() => handleSelect(icon.url)}>
<Icon icon={icon.url} class="h-6 w-6" /> <Icon icon={icon.url} size={6} />
</button> </button>
{/each} {/each}
</div> </div>
+2 -2
View File
@@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import IconPicker from "@app/components/IconPicker.svelte" import IconPicker from "@app/components/IconPicker.svelte"
type Props = { type Props = {
+3 -2
View File
@@ -1,4 +1,5 @@
<script lang="ts"> <script lang="ts">
import Card from "@lib/components2/Card.svelte"
import IconPicker from "@app/components/IconPicker.svelte" import IconPicker from "@app/components/IconPicker.svelte"
type Props = { type Props = {
@@ -8,6 +9,6 @@
const {onSelect}: Props = $props() const {onSelect}: Props = $props()
</script> </script>
<div class="w-96 rounded-box bg-base-100 p-4 shadow-2xl"> <Card class="w-96">
<IconPicker {onSelect} /> <IconPicker {onSelect} />
</div> </Card>
+28 -27
View File
@@ -1,41 +1,42 @@
<script lang="ts"> <script lang="ts">
import Link from "@lib/components/Link.svelte" import Link from "@lib/components2/Link.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Modal from "@lib/components/Modal.svelte" import Text from "@lib/components2/Text.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import {PLATFORM_NAME} from "@app/env" import {PLATFORM_NAME} from "@app/env"
</script> </script>
<Modal <Modal>
><ModalBody> <ModalBody>
<ModalHeader> <ModalHeader>
<ModalTitle>What is a bunker link?</ModalTitle> <ModalTitle>What is a bunker link?</ModalTitle>
</ModalHeader> </ModalHeader>
<p> <Text>
<Link external class="link" href="https://nostr.com/">Nostr</Link> uses "keys" instead of passwords <Link external styled href="https://nostr.com/">Nostr</Link> uses "keys" instead of passwords
to identify users. This allows users to own their social identity instead of renting it from a tech to identify users. This allows users to own their social identity instead of renting it from a
company, and can bring it with them from app to app. tech company, and can bring it with them from app to app.
</p> </Text>
<p> <Text>
A good way to manage your keys is to use a remote signing application. These apps can hold A good way to manage your keys is to use a remote signing application. These apps can hold your
your keys and log you in remotely to as many applications as you like, without risking loss or keys and log you in remotely to as many applications as you like, without risking loss or theft
theft of your keys. of your keys.
</p> </Text>
<p> <Text>
One way to log in with a remote signer is using a "bunker link" which is more secure and One way to log in with a remote signer is using a "bunker link" which is more secure and
decentralized than other solutions. Check your signer for a link beginning with "bunker://", decentralized than other solutions. Check your signer for a link beginning with "bunker://",
copy it into {PLATFORM_NAME}, and you should be good to go! copy it into {PLATFORM_NAME}, and you should be good to go!
</p> </Text>
<p> <Text>
If you don't have a signer yet, <Link external class="link" href="https://nsec.app/" If you don't have a signer yet, <Link external styled href="https://nsec.app/">nsec.app</Link>
>nsec.app</Link>
is a great way to get started. You can find more signers on <Link is a great way to get started. You can find more signers on <Link
external external
class="link" styled
href="https://nostrapps.com#signers">nostrapps.com</Link href="https://nostrapps.com#signers">nostrapps.com</Link
>. >.
</p> </Text>
<Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button> <Button variant="primary" onclick={() => history.back()}>Got it</Button>
</ModalBody></Modal> </ModalBody>
</Modal>
+19 -19
View File
@@ -1,31 +1,31 @@
<script lang="ts"> <script lang="ts">
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components2/Link.svelte"
import Modal from "@lib/components/Modal.svelte" import Text from "@lib/components2/Text.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components2/ModalTitle.svelte"
import {PLATFORM_NAME} from "@app/env" import {PLATFORM_NAME} from "@app/env"
</script> </script>
<Modal <Modal>
><ModalBody> <ModalBody>
<ModalHeader> <ModalHeader>
<ModalTitle>What is a nostr address?</ModalTitle> <ModalTitle>What is a nostr address?</ModalTitle>
</ModalHeader> </ModalHeader>
<p> <Text>
{PLATFORM_NAME} hosts spaces on the <Link external href="https://nostr.com/" class="underline" {PLATFORM_NAME} hosts spaces on the <Link external styled href="https://nostr.com/"
>Nostr protocol</Link >Nostr protocol</Link
>. Nostr uses "nostr addresses" to make it easier for people to find you, without having to >. Nostr uses "nostr addresses" to make it easier for people to find you, without having to
memorize your public key (your user id). memorize your public key (your user id).
</p> </Text>
<p> <Text>
There are several providers of nostr addresses, including several clients. You can find a list There are several providers of nostr addresses, including several clients. You can find a list
and more information on <Link and more information on <Link external styled href="https://nostr.how/en/guides/get-verified"
external >nostr.how</Link
href="https://nostr.how/en/guides/get-verified"
class="underline">nostr.how</Link
>. >.
</p> </Text>
<Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button> <Button variant="primary" onclick={() => history.back()}>Got it</Button>
</ModalBody></Modal> </ModalBody>
</Modal>
+20 -19
View File
@@ -1,15 +1,16 @@
<script lang="ts"> <script lang="ts">
import {session} from "@welshman/app" import {session} from "@welshman/app"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components2/Link.svelte"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import CheckCircle from "@assets/icons/check-circle.svg?dataurl" import CheckCircle from "@assets/icons/check-circle.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components2/ModalFooter.svelte"
import Text from "@lib/components2/Text.svelte"
import KeyRecoveryRequest from "@app/components/KeyRecoveryRequest.svelte" import KeyRecoveryRequest from "@app/components/KeyRecoveryRequest.svelte"
import {PLATFORM_NAME} from "@app/env" import {PLATFORM_NAME} from "@app/env"
import {pushModal} from "@app/modal" import {pushModal} from "@app/modal"
@@ -24,36 +25,36 @@
<ModalHeader> <ModalHeader>
<ModalTitle>What is a private key?</ModalTitle> <ModalTitle>What is a private key?</ModalTitle>
</ModalHeader> </ModalHeader>
<p> <Text>
Most online services keep track of users by giving them a username and password. This gives Most online services keep track of users by giving them a username and password. This gives
the service <strong>total control</strong> over their users, allowing them to ban them at any time, the service <strong>total control</strong> over their users, allowing them to ban them at any time,
or sell their activity. or sell their activity.
</p> </Text>
<p> <Text>
On <Link external href="https://nostr.com/">Nostr</Link>, <strong>you</strong> control your On <Link external styled href="https://nostr.com/">Nostr</Link>, <strong>you</strong> control your
own identity and social data, through the magic of cryptography. The basic idea is that you own identity and social data, through the magic of cryptography. The basic idea is that you
have a have a
<strong>public key</strong>, which acts as your user ID, and a <strong>public key</strong>, which acts as your user ID, and a
<strong>private key</strong> which allows you to prove your identity. <strong>private key</strong> which allows you to prove your identity.
</p> </Text>
{#if $session?.email} {#if $session?.email}
<p> <Text>
It's very important to keep private keys safe, but this can sometimes be tricky, which is It's very important to keep private keys safe, but this can sometimes be tricky, which is
why {PLATFORM_NAME} why {PLATFORM_NAME}
supports a traditional account-based login for new users. supports a traditional account-based login for new users.
</p> </Text>
<p>If you'd like to switch to self-custody, please click below to get started.</p> <Text>If you'd like to switch to self-custody, please click below to get started.</Text>
{:else} {:else}
<Button class="btn btn-primary" onclick={back}>Got it</Button> <Button variant="primary" onclick={back}>Got it</Button>
{/if} {/if}
</ModalBody> </ModalBody>
{#if $session?.email} {#if $session?.email}
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
<Button class="btn btn-primary" onclick={startRecoveryRequest}> <Button variant="primary" onclick={startRecoveryRequest}>
<Icon icon={CheckCircle} /> <Icon icon={CheckCircle} />
I want to hold my own keys I want to hold my own keys
</Button> </Button>
+17 -16
View File
@@ -1,10 +1,11 @@
<script lang="ts"> <script lang="ts">
import Link from "@lib/components/Link.svelte" import Link from "@lib/components2/Link.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import Text from "@lib/components2/Text.svelte"
</script> </script>
<Modal <Modal
@@ -12,21 +13,21 @@
<ModalHeader> <ModalHeader>
<ModalTitle>What is nostr?</ModalTitle> <ModalTitle>What is nostr?</ModalTitle>
</ModalHeader> </ModalHeader>
<p> <Text>
<Link external href="https://nostr.com/" class="link">Nostr</Link> is way to build social apps that <Link external styled href="https://nostr.com/">Nostr</Link> is way to build social apps that
talk to each other. Users own their social identity instead of renting it from a tech company, and talk to each other. Users own their social identity instead of renting it from a tech company, and
can take it with them. can take it with them.
</p> </Text>
<p> <Text>
If you'd like to learn more about what other apps exist in the nostr ecosystem, please visit <Link If you'd like to learn more about what other apps exist in the nostr ecosystem, please visit <Link
external external
class="link" styled
href="https://nostrapps.com/">nostrapps.com</Link href="https://nostrapps.com/">nostrapps.com</Link
>. >.
</p> </Text>
<p> <Text>
To learn more about how to manage your keys, or to set up an account, try To learn more about how to manage your keys, or to set up an account, try
<Link external class="link" href="https://nosta.me/">nosta.me</Link>. <Link external styled href="https://nosta.me/">nosta.me</Link>.
</p> </Text>
<Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button> <Button variant="primary" onclick={() => history.back()}>Got it</Button>
</ModalBody></Modal> </ModalBody></Modal>
+14 -13
View File
@@ -1,11 +1,12 @@
<script lang="ts"> <script lang="ts">
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components2/Link.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components2/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import Text from "@lib/components2/Text.svelte"
import {PLATFORM_NAME} from "@app/env" import {PLATFORM_NAME} from "@app/env"
</script> </script>
@@ -14,19 +15,19 @@
<ModalHeader> <ModalHeader>
<ModalTitle>What is a relay?</ModalTitle> <ModalTitle>What is a relay?</ModalTitle>
</ModalHeader> </ModalHeader>
<p> <Text>
{PLATFORM_NAME} hosts spaces on the <Link external href="https://nostr.com/" class="underline" {PLATFORM_NAME} hosts spaces on the <Link external styled href="https://nostr.com/"
>Nostr protocol</Link >Nostr protocol</Link
>. Nostr uses "relays" to host data, which are special-purpose servers that speak nostr's >. Nostr uses "relays" to host data, which are special-purpose servers that speak nostr's
language. This means that anyone can host their own data, making the web more decentralized language. This means that anyone can host their own data, making the web more decentralized
and resilient. and resilient.
</p> </Text>
<p> <Text>
Different relays have different policies for access control and content retention. Be sure to Different relays have different policies for access control and content retention. Be sure to
double check that you have access to the relays you try to use by visiting their website. double check that you have access to the relays you try to use by visiting their website.
</p> </Text>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button> <Button variant="primary" onclick={() => history.back()}>Got it</Button>
</ModalFooter> </ModalFooter>
</Modal> </Modal>
+15 -14
View File
@@ -1,10 +1,11 @@
<script lang="ts"> <script lang="ts">
import Link from "@lib/components/Link.svelte" import Link from "@lib/components2/Link.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import Text from "@lib/components2/Text.svelte"
const back = () => history.back() const back = () => history.back()
</script> </script>
@@ -14,21 +15,21 @@
<ModalHeader> <ModalHeader>
<ModalTitle>What are digital signatures?</ModalTitle> <ModalTitle>What are digital signatures?</ModalTitle>
</ModalHeader> </ModalHeader>
<p> <Text>
Most online services ask their users to trust them that they're being honest, and they usually Most online services ask their users to trust them that they're being honest, and they usually
are. However, traditional social media platforms have the ability to <strong are. However, traditional social media platforms have the ability to <strong
>create forged content</strong> that can appear to be genuinely authored, but which are actually >create forged content</strong> that can appear to be genuinely authored, but which are actually
counterfeit. counterfeit.
</p> </Text>
<p> <Text>
On <Link external href="https://nostr.com/">Nostr</Link>, all your content is authenticated On <Link external styled href="https://nostr.com/">Nostr</Link>, all your content is authenticated
using <strong>digital signatures</strong>, which cryptographically tie a particular person to using <strong>digital signatures</strong>, which cryptographically tie a particular person to
a given post or message. a given post or message.
</p> </Text>
<p> <Text>
The result is that you don't normally have to trust service providers not to tamper with the The result is that you don't normally have to trust service providers not to tamper with the
information flowing through the network — instead, your client software can prove that a given information flowing through the network — instead, your client software can prove that a given
piece of data is authentic. piece of data is authentic.
</p> </Text>
<Button class="btn btn-primary" onclick={back}>Got it</Button> <Button variant="primary" onclick={back}>Got it</Button>
</ModalBody></Modal> </ModalBody></Modal>
+9 -9
View File
@@ -1,13 +1,13 @@
<script lang="ts"> <script lang="ts">
import {deriveZapperForPubkey} from "@welshman/app" import {deriveZapperForPubkey} from "@welshman/app"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components2/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import ProfileLink from "@app/components/ProfileLink.svelte" import ProfileLink from "@app/components/ProfileLink.svelte"
const {pubkey} = $props() const {pubkey} = $props()
@@ -23,7 +23,7 @@
<ModalTitle>Unable to Zap</ModalTitle> <ModalTitle>Unable to Zap</ModalTitle>
</ModalHeader> </ModalHeader>
<p> <p>
Zapping <ProfileLink {pubkey} class="text-primary!" /> isn't possible right now because Zapping <ProfileLink {pubkey} class="cl-text-primary" /> isn't possible right now because
{#if $zapper} {#if $zapper}
their zap receiver isn't correctly set up. their zap receiver isn't correctly set up.
{:else} {:else}
@@ -32,7 +32,7 @@
</p> </p>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button variant="ghost" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
@@ -4,7 +4,7 @@
import CloseCircle from "@assets/icons/close-circle.svg?dataurl" import CloseCircle from "@assets/icons/close-circle.svg?dataurl"
import AddCircle from "@assets/icons/add-circle.svg?dataurl" import AddCircle from "@assets/icons/add-circle.svg?dataurl"
import GallerySend from "@assets/icons/gallery-send.svg?dataurl" import GallerySend from "@assets/icons/gallery-send.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import {uploadFile} from "@app/uploads" import {uploadFile} from "@app/uploads"
interface Props { interface Props {
@@ -79,28 +79,28 @@
<label <label
for={id} for={id}
aria-label="Drag and drop files here." aria-label="Drag and drop files here."
style="background-image: url({url});" style="background-image: url({url}); background-color: var(--cl-bg-alt); border-color: {active
class="relative flex h-24 w-24 shrink-0 cursor-pointer items-center justify-center rounded-full border-2 border-solid border-base-content bg-base-300 bg-cover bg-center transition-all" ? 'var(--cl-primary)'
: 'var(--cl-border)'};"
class="relative flex h-24 w-24 shrink-0 cursor-pointer items-center justify-center rounded-full border-2 border-solid bg-cover bg-center transition-all"
class:transparent={!url} class:transparent={!url}
class:border-primary={active}
ondragenter={stopPropagation(preventDefault(onDragEnter))} ondragenter={stopPropagation(preventDefault(onDragEnter))}
ondragover={stopPropagation(preventDefault(onDragOver))} ondragover={stopPropagation(preventDefault(onDragOver))}
ondragleave={stopPropagation(preventDefault(onDragLeave))} ondragleave={stopPropagation(preventDefault(onDragLeave))}
ondrop={stopPropagation(preventDefault(onDrop))}> ondrop={stopPropagation(preventDefault(onDrop))}>
<div <div
class="absolute right-0 top-0 h-5 w-5 overflow-hidden rounded-full bg-primary" class="absolute right-0 top-0 h-5 w-5 overflow-hidden rounded-full"
class:bg-error={url} style="background-color: {url ? 'var(--cl-danger)' : 'var(--cl-primary)'};">
class:bg-primary={!url}>
{#if url} {#if url}
<span <span
role="button" role="button"
tabindex="-1" tabindex="-1"
onmousedown={stopPropagation(onClear)} onmousedown={stopPropagation(onClear)}
ontouchstart={stopPropagation(onClear)}> ontouchstart={stopPropagation(onClear)}>
<Icon icon={CloseCircle} class="scale-150 bg-base-300!" /> <Icon icon={CloseCircle} class="scale-150 cl-surface-alt" />
</span> </span>
{:else} {:else}
<Icon icon={AddCircle} class="scale-150 bg-base-300!" /> <Icon icon={AddCircle} class="scale-150 cl-surface-alt" />
{/if} {/if}
</div> </div>
{#if !url} {#if !url}
+15 -15
View File
@@ -7,14 +7,14 @@
import ArrowDown from "@assets/icons/arrow-down.svg?dataurl" import ArrowDown from "@assets/icons/arrow-down.svg?dataurl"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Field from "@lib/components/Field.svelte" import Field from "@lib/components2/Field.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components2/ModalFooter.svelte"
import ProgressBar from "@app/components/ProgressBar.svelte" import ProgressBar from "@app/components/ProgressBar.svelte"
import {pushToast} from "@app/toast" import {pushToast} from "@app/toast"
import {PLATFORM_NAME} from "@app/env" import {PLATFORM_NAME} from "@app/env"
@@ -129,9 +129,9 @@
Password* Password*
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<label class="input input-bordered flex w-full items-center gap-2"> <label class="input-cl input-cl-group w-full">
<Icon icon={Key} /> <Icon icon={Key} />
<input bind:value={password} onchange={onPasswordChange} class="grow" type="password" /> <input bind:value={password} onchange={onPasswordChange} type="password" />
</label> </label>
{/snippet} {/snippet}
{#snippet info()} {#snippet info()}
@@ -139,12 +139,12 @@
{/snippet} {/snippet}
</Field> </Field>
{/if} {/if}
<div class="flex flex-col"> <div class="flex flex-col gap-2">
<Button class="btn {didDownload ? 'btn-neutral' : 'btn-primary'}" onclick={downloadKey}> <Button variant={didDownload ? "secondary" : "primary"} onclick={downloadKey}>
Download my key Download my key
<Icon icon={ArrowDown} /> <Icon icon={ArrowDown} />
</Button> </Button>
<Button class="btn btn-link no-underline" onclick={toggleUsePassword}> <Button variant="ghost" onclick={toggleUsePassword}>
{#if usePassword} {#if usePassword}
Nevermind, I want to download the plain version Nevermind, I want to download the plain version
{:else} {:else}
@@ -157,11 +157,11 @@
<ProgressBar current={step} total={totalSteps} /> <ProgressBar current={step} total={totalSteps} />
{/if} {/if}
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button variant="ghost" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
<Button disabled={!didDownload} class="btn btn-primary" type="submit"> <Button disabled={!didDownload} variant="primary" type="submit">
{submitText} {submitText}
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
+12 -12
View File
@@ -6,16 +6,16 @@
import {preventDefault} from "@lib/html" import {preventDefault} from "@lib/html"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components2/Spinner.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components2/ModalFooter.svelte"
import StringMultiInput from "@lib/components/StringMultiInput.svelte" import StringMultiInput from "@lib/components2/StringMultiInput.svelte"
import KeyDownload from "@app/components/KeyDownload.svelte" import KeyDownload from "@app/components/KeyDownload.svelte"
import {pushToast} from "@app/toast" import {pushToast} from "@app/toast"
import {pushModal, clearModals} from "@app/modal" import {pushModal, clearModals} from "@app/modal"
@@ -87,11 +87,11 @@
<StringMultiInput bind:value={otps} placeholder="Enter your recovery codes..." /> <StringMultiInput bind:value={otps} placeholder="Enter your recovery codes..." />
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button variant="ghost" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
<Button type="submit" class="btn btn-primary" disabled={loading || otps.length < 2}> <Button type="submit" variant="primary" disabled={loading || otps.length < 2}>
<Spinner {loading}>Confirm recovery</Spinner> <Spinner {loading}>Confirm recovery</Spinner>
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
+11 -11
View File
@@ -5,15 +5,15 @@
import {preventDefault} from "@lib/html" import {preventDefault} from "@lib/html"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components2/Spinner.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components2/ModalFooter.svelte"
import {pushModal} from "@app/modal" import {pushModal} from "@app/modal"
import KeyRecoveryConfirm from "@app/components/KeyRecoveryConfirm.svelte" import KeyRecoveryConfirm from "@app/components/KeyRecoveryConfirm.svelte"
@@ -59,11 +59,11 @@
</p> </p>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button variant="ghost" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
<Button type="submit" class="btn btn-primary" disabled={loading}> <Button type="submit" variant="primary" disabled={loading}>
<Spinner {loading}>Request recovery</Spinner> <Spinner {loading}>Request recovery</Spinner>
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
+17 -15
View File
@@ -1,12 +1,14 @@
<script lang="ts"> <script lang="ts">
import Login from "@assets/icons/login-3.svg?dataurl" import Login from "@assets/icons/login-3.svg?dataurl"
import AddCircle from "@assets/icons/add-circle.svg?dataurl" import AddCircle from "@assets/icons/add-circle.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components2/Link.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import CardButton from "@lib/components/CardButton.svelte" import CardButton from "@lib/components2/CardButton.svelte"
import Heading from "@lib/components2/Heading.svelte"
import Text from "@lib/components2/Text.svelte"
import LogIn from "@app/components/LogIn.svelte" import LogIn from "@app/components/LogIn.svelte"
import SignUp from "@app/components/SignUp.svelte" import SignUp from "@app/components/SignUp.svelte"
import {PLATFORM_TERMS, PLATFORM_PRIVACY, PLATFORM_NAME} from "@app/env" import {PLATFORM_TERMS, PLATFORM_PRIVACY, PLATFORM_NAME} from "@app/env"
@@ -20,11 +22,11 @@
<Modal> <Modal>
<ModalBody> <ModalBody>
<div class="py-2"> <div class="py-2">
<h1 class="heading">Welcome to {PLATFORM_NAME}!</h1> <Heading level={1} class="text-center">Welcome to {PLATFORM_NAME}!</Heading>
<p class="text-center">The chat app built for self-hosted communities.</p> <Text class="text-center">The chat app built for self-hosted communities.</Text>
</div> </div>
<Button onclick={logIn}> <Button onclick={logIn} block class="!p-0">
<CardButton class="btn-primary"> <CardButton>
{#snippet icon()} {#snippet icon()}
<div><Icon icon={Login} size={7} /></div> <div><Icon icon={Login} size={7} /></div>
{/snippet} {/snippet}
@@ -36,7 +38,7 @@
{/snippet} {/snippet}
</CardButton> </CardButton>
</Button> </Button>
<Button onclick={signUp} class="btn-neutral"> <Button onclick={signUp} block class="!p-0">
<CardButton> <CardButton>
{#snippet icon()} {#snippet icon()}
<div><Icon icon={AddCircle} size={7} /></div> <div><Icon icon={AddCircle} size={7} /></div>
@@ -49,10 +51,10 @@
{/snippet} {/snippet}
</CardButton> </CardButton>
</Button> </Button>
<p class="text-center text-xs opacity-75"> <Text size="sm" muted class="text-center">
By using {PLATFORM_NAME}, you consent to our By using {PLATFORM_NAME}, you consent to our
<Link external class="link" href={PLATFORM_TERMS}>Terms of Service</Link> and <Link external styled href={PLATFORM_TERMS}>Terms of Service</Link> and
<Link external class="link" href={PLATFORM_PRIVACY}>Privacy Policy</Link>. <Link external styled href={PLATFORM_PRIVACY}>Privacy Policy</Link>.
</p> </Text>
</ModalBody> </ModalBody>
</Modal> </Modal>
+27 -23
View File
@@ -8,11 +8,13 @@
import Cpu from "@assets/icons/cpu-bolt.svg?dataurl" import Cpu from "@assets/icons/cpu-bolt.svg?dataurl"
import Compass from "@assets/icons/compass-big.svg?dataurl" import Compass from "@assets/icons/compass-big.svg?dataurl"
import Key from "@assets/icons/key.svg?dataurl" import Key from "@assets/icons/key.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components2/Link.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Heading from "@lib/components2/Heading.svelte"
import Text from "@lib/components2/Text.svelte"
import SignUp from "@app/components/SignUp.svelte" import SignUp from "@app/components/SignUp.svelte"
import InfoNostr from "@app/components/InfoNostr.svelte" import InfoNostr from "@app/components/InfoNostr.svelte"
import LogInBunker from "@app/components/LogInBunker.svelte" import LogInBunker from "@app/components/LogInBunker.svelte"
@@ -94,16 +96,17 @@
<Modal> <Modal>
<ModalBody> <ModalBody>
<h1 class="heading">Log in with Nostr</h1> <Heading level={1} class="text-center">Log in with Nostr</Heading>
<p class="m-auto max-w-sm text-center"> <Text class="m-auto max-w-sm text-center">
{PLATFORM_NAME} is built using the {PLATFORM_NAME} is built using the
<Button class="link" onclick={() => pushModal(InfoNostr)}>nostr protocol</Button>, which <Button variant="ghost" class="inline cl-link" onclick={() => pushModal(InfoNostr)}
allows you to own your social identity. >nostr protocol</Button
</p> >, which allows you to own your social identity.
</Text>
{#if getNip07()} {#if getNip07()}
<Button {disabled} onclick={loginWithNip07} class="btn btn-primary"> <Button variant="primary" block {disabled} onclick={loginWithNip07}>
{#if loading === "nip07"} {#if loading === "nip07"}
<span class="loading loading-spinner mr-3"></span> <span class="cl-spinner mr-3"></span>
{:else} {:else}
<Icon icon={Widget} /> <Icon icon={Widget} />
{/if} {/if}
@@ -111,9 +114,9 @@
</Button> </Button>
{/if} {/if}
{#each signers as app} {#each signers as app}
<Button {disabled} class="btn btn-primary" onclick={() => loginWithNip55(app)}> <Button variant="primary" block {disabled} onclick={() => loginWithNip55(app)}>
{#if loading === "nip55"} {#if loading === "nip55"}
<span class="loading loading-spinner mr-3"></span> <span class="cl-spinner mr-3"></span>
{:else} {:else}
<img src={app.iconUrl} alt={app.name} width="20" height="20" /> <img src={app.iconUrl} alt={app.name} width="20" height="20" />
{/if} {/if}
@@ -121,26 +124,27 @@
</Button> </Button>
{/each} {/each}
{#if hasPomade && !hasSigner} {#if hasPomade && !hasSigner}
<Button {disabled} onclick={loginWithEmail} class="btn btn-primary"> <Button variant="primary" block {disabled} onclick={loginWithEmail}>
<Icon icon={Letter} /> <Icon icon={Letter} />
Log in with Email Log in with Email
</Button> </Button>
{/if} {/if}
<Button <Button
variant={hasSigner || hasPomade ? "secondary" : "primary"}
block
onclick={loginWithBunker} onclick={loginWithBunker}
{disabled} {disabled}>
class="btn {hasSigner || hasPomade ? 'btn-neutral' : 'btn-primary'}">
<Icon icon={Cpu} /> <Icon icon={Cpu} />
Log in with Remote Signer Log in with Remote Signer
</Button> </Button>
{#if hasPomade && hasSigner} {#if hasPomade && hasSigner}
<Button {disabled} onclick={loginWithEmail} class="btn"> <Button variant="ghost" block {disabled} onclick={loginWithEmail}>
<Icon icon={Letter} /> <Icon icon={Letter} />
Log in with Email Log in with Email
</Button> </Button>
{/if} {/if}
{#if !hasSigner} {#if !hasSigner}
<Button {disabled} onclick={loginWithKey} class="btn btn-neutral"> <Button variant="secondary" block {disabled} onclick={loginWithKey}>
<Icon icon={Key} /> <Icon icon={Key} />
Log in with Key Log in with Key
</Button> </Button>
@@ -150,14 +154,14 @@
external external
{disabled} {disabled}
href="https://nostrapps.com#signers" href="https://nostrapps.com#signers"
class="btn {hasSigner || hasPomade ? '' : 'btn-neutral'}"> class="btn-cl btn-cl-block {hasSigner || hasPomade ? 'btn-cl-ghost' : 'btn-cl-secondary'}">
<Icon icon={Compass} /> <Icon icon={Compass} />
Browse Signer Apps Browse Signer Apps
</Link> </Link>
{/if} {/if}
<div class="text-sm"> <Text size="sm">
Need an account? Need an account?
<Button class="link" onclick={signUp}>Register instead</Button> <Button variant="ghost" class="inline cl-link" onclick={signUp}>Register instead</Button>
</div> </Text>
</ModalBody> </ModalBody>
</Modal> </Modal>
+13 -13
View File
@@ -6,17 +6,17 @@
import {makeSecret} from "@welshman/util" import {makeSecret} from "@welshman/util"
import {loginWithNip01, loginWithNip46} from "@welshman/app" import {loginWithNip01, loginWithNip46} from "@welshman/app"
import {preventDefault} from "@lib/html" import {preventDefault} from "@lib/html"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components2/Spinner.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components2/ModalFooter.svelte"
import BunkerConnect from "@app/components/BunkerConnect.svelte" import BunkerConnect from "@app/components/BunkerConnect.svelte"
import BunkerUrl from "@app/components/BunkerUrl.svelte" import BunkerUrl from "@app/components/BunkerUrl.svelte"
import {Nip46Controller} from "@app/nip46" import {Nip46Controller} from "@app/nip46"
@@ -151,20 +151,20 @@
<BunkerConnect {controller} /> <BunkerConnect {controller} />
{:else} {:else}
<BunkerUrl {controller} /> <BunkerUrl {controller} />
<Button class="btn {$bunker ? 'btn-neutral' : 'btn-primary'}" onclick={selectConnect} <Button variant={$bunker ? "secondary" : "primary"} onclick={selectConnect}
>Log in with a QR code instead</Button> >Log in with a QR code instead</Button>
{#if isIos} {#if isIos}
<Button class="btn btn-neutral" onclick={openSigner}>Open in Signer</Button> <Button variant="secondary" onclick={openSigner}>Open in Signer</Button>
{/if} {/if}
{/if} {/if}
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back} disabled={$loading}> <Button variant="ghost" onclick={back} disabled={$loading}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
{#if mode === "bunker"} {#if mode === "bunker"}
<Button type="submit" class="btn btn-primary" disabled={$loading || !$bunker}> <Button type="submit" variant="primary" disabled={$loading || !$bunker}>
<Spinner loading={$loading}>Next</Spinner> <Spinner loading={$loading}>Next</Spinner>
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
+17 -17
View File
@@ -2,20 +2,20 @@
import {uniq} from "@welshman/lib" import {uniq} from "@welshman/lib"
import {Client} from "@pomade/core" import {Client} from "@pomade/core"
import {preventDefault} from "@lib/html" import {preventDefault} from "@lib/html"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components2/Spinner.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import FieldInline from "@lib/components/FieldInline.svelte" import FieldInline from "@lib/components2/FieldInline.svelte"
import Letter from "@assets/icons/letter.svg?dataurl" import Letter from "@assets/icons/letter.svg?dataurl"
import Key from "@assets/icons/key.svg?dataurl" import Key from "@assets/icons/key.svg?dataurl"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components2/ModalFooter.svelte"
import LogInOTP from "@app/components/LogInOTP.svelte" import LogInOTP from "@app/components/LogInOTP.svelte"
import LogInSelect from "@app/components/LogInSelect.svelte" import LogInSelect from "@app/components/LogInSelect.svelte"
import {deleteDeactivatedPomadeSessions, loginWithPomade} from "@app/pomade" import {deleteDeactivatedPomadeSessions, loginWithPomade} from "@app/pomade"
@@ -96,9 +96,9 @@
<p>Email*</p> <p>Email*</p>
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<label class="input input-bordered flex w-full items-center gap-2"> <label class="input-cl input-cl-group">
<Icon icon={Letter} /> <Icon icon={Letter} />
<input type="email" bind:value={email} /> <input type="email" class="input-cl-bare" bind:value={email} />
</label> </label>
{/snippet} {/snippet}
</FieldInline> </FieldInline>
@@ -107,24 +107,24 @@
<p>Password*</p> <p>Password*</p>
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<label class="input input-bordered flex w-full items-center gap-2"> <label class="input-cl input-cl-group">
<Icon icon={Key} /> <Icon icon={Key} />
<input type="password" bind:value={password} /> <input type="password" class="input-cl-bare" bind:value={password} />
</label> </label>
{/snippet} {/snippet}
</FieldInline> </FieldInline>
<p class="text-sm"> <p class="text-sm">
Forgot your password? <Button class="link" onclick={loginWithOTP} Forgot your password? <Button class="cl-link p-0" onclick={loginWithOTP}
>Log in with a one-time access code</Button >Log in with a one-time access code</Button
>. >.
</p> </p>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back} disabled={loading}> <Button variant="ghost" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
<Button type="submit" class="btn btn-primary" disabled={loading || !email || !password}> <Button type="submit" variant="primary" disabled={loading || !email || !password}>
<Spinner {loading}>Log in</Spinner> <Spinner {loading}>Log in</Spinner>
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
+19 -18
View File
@@ -4,21 +4,22 @@
import {decrypt} from "nostr-tools/nip49" import {decrypt} from "nostr-tools/nip49"
import {preventDefault} from "@lib/html" import {preventDefault} from "@lib/html"
import {nsecDecode} from "@lib/util" import {nsecDecode} from "@lib/util"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components2/Spinner.svelte"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components2/Link.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import FieldInline from "@lib/components/FieldInline.svelte" import FieldInline from "@lib/components2/FieldInline.svelte"
import Alert from "@lib/components2/Alert.svelte"
import Key from "@assets/icons/key.svg?dataurl" import Key from "@assets/icons/key.svg?dataurl"
import Danger from "@assets/icons/danger-triangle.svg?dataurl" import Danger from "@assets/icons/danger-triangle.svg?dataurl"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components2/ModalFooter.svelte"
import {clearModals} from "@app/modal" import {clearModals} from "@app/modal"
import {setChecked} from "@app/notifications" import {setChecked} from "@app/notifications"
import {pushToast} from "@app/toast" import {pushToast} from "@app/toast"
@@ -85,7 +86,7 @@
<p>Your Key*</p> <p>Your Key*</p>
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<label class="input input-bordered flex w-full items-center gap-2"> <label class="input-cl input-cl-group w-full">
<Icon icon={Key} /> <Icon icon={Key} />
<input type="password" bind:value={keyInput} placeholder="nsec1..." /> <input type="password" bind:value={keyInput} placeholder="nsec1..." />
</label> </label>
@@ -97,31 +98,31 @@
<p>Password*</p> <p>Password*</p>
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<label class="input input-bordered flex w-full items-center gap-2"> <label class="input-cl input-cl-group w-full">
<Icon icon={Key} /> <Icon icon={Key} />
<input type="password" bind:value={password} placeholder="Your password" /> <input type="password" bind:value={password} placeholder="Your password" />
</label> </label>
{/snippet} {/snippet}
</FieldInline> </FieldInline>
{/if} {/if}
<div class="card2 card2-sm bg-alt flex flex-col gap-2 text-sm"> <Alert variant="warning" class="flex-col text-sm">
<strong class="flex items-center gap-2"> <strong class="flex items-center gap-2">
<Icon icon={Danger} /> <Icon icon={Danger} />
Please note! Please note!
</strong> </strong>
<p> <p>
Logging in this way is not a best practice. For better security, please consider using a Logging in this way is not a best practice. For better security, please consider using a
<Link external href="https://nostrapps.com#signers" class="link">signer app</Link> <Link external styled href="https://nostrapps.com#signers">signer app</Link>
to keep your keys safe. to keep your keys safe.
</p> </p>
</div> </Alert>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back} disabled={loading}> <Button variant="ghost" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
<Button type="submit" class="btn btn-primary" disabled={!canSubmit}> <Button type="submit" variant="primary" disabled={!canSubmit}>
<Spinner {loading}>Log in</Spinner> <Spinner {loading}>Log in</Spinner>
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
+13 -13
View File
@@ -1,19 +1,19 @@
<script lang="ts"> <script lang="ts">
import {Client} from "@pomade/core" import {Client} from "@pomade/core"
import {preventDefault} from "@lib/html" import {preventDefault} from "@lib/html"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components2/Spinner.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import FieldInline from "@lib/components/FieldInline.svelte" import FieldInline from "@lib/components2/FieldInline.svelte"
import Letter from "@assets/icons/letter.svg?dataurl" import Letter from "@assets/icons/letter.svg?dataurl"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components2/ModalFooter.svelte"
import LogInOTPConfirm from "@app/components/LogInOTPConfirm.svelte" import LogInOTPConfirm from "@app/components/LogInOTPConfirm.svelte"
import {POMADE_NETWORK_ERROR_MESSAGE} from "@app/pomade" import {POMADE_NETWORK_ERROR_MESSAGE} from "@app/pomade"
import {pushModal} from "@app/modal" import {pushModal} from "@app/modal"
@@ -69,7 +69,7 @@
<p>Email*</p> <p>Email*</p>
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<label class="input input-bordered flex w-full items-center gap-2"> <label class="input-cl input-cl-group w-full">
<Icon icon={Letter} /> <Icon icon={Letter} />
<input type="email" bind:value={email} /> <input type="email" bind:value={email} />
</label> </label>
@@ -77,11 +77,11 @@
</FieldInline> </FieldInline>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back} disabled={loading}> <Button variant="ghost" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
<Button type="submit" class="btn btn-primary" disabled={loading || !email}> <Button type="submit" variant="primary" disabled={loading || !email}>
<Spinner {loading}>Log in</Spinner> <Spinner {loading}>Log in</Spinner>
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
+12 -12
View File
@@ -2,18 +2,18 @@
import {uniq} from "@welshman/lib" import {uniq} from "@welshman/lib"
import {Client} from "@pomade/core" import {Client} from "@pomade/core"
import {preventDefault} from "@lib/html" import {preventDefault} from "@lib/html"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components2/Spinner.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components2/ModalFooter.svelte"
import StringMultiInput from "@lib/components/StringMultiInput.svelte" import StringMultiInput from "@lib/components2/StringMultiInput.svelte"
import LogInSelect from "@app/components/LogInSelect.svelte" import LogInSelect from "@app/components/LogInSelect.svelte"
import {pushModal, clearModals} from "@app/modal" import {pushModal, clearModals} from "@app/modal"
import {setChecked} from "@app/notifications" import {setChecked} from "@app/notifications"
@@ -99,11 +99,11 @@
<StringMultiInput bind:value={otps} placeholder="Enter your login codes..." /> <StringMultiInput bind:value={otps} placeholder="Enter your login codes..." />
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back} disabled={loading}> <Button variant="ghost" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
<Button type="submit" class="btn btn-primary" disabled={loading || otps.length < 3}> <Button type="submit" variant="primary" disabled={loading || otps.length < 3}>
<Spinner {loading}>Log In</Spinner> <Spinner {loading}>Log In</Spinner>
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
+12 -11
View File
@@ -2,16 +2,16 @@
import type {AccountOption} from "@pomade/core" import type {AccountOption} from "@pomade/core"
import {Client} from "@pomade/core" import {Client} from "@pomade/core"
import {uniqBy} from "@welshman/lib" import {uniqBy} from "@welshman/lib"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components2/Spinner.svelte"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components2/ModalFooter.svelte"
import Profile from "@app/components/Profile.svelte" import Profile from "@app/components/Profile.svelte"
import {deleteDeactivatedPomadeSessions, loginWithPomade} from "@app/pomade" import {deleteDeactivatedPomadeSessions, loginWithPomade} from "@app/pomade"
import {getPomadeLoginFailureMessage, POMADE_NETWORK_ERROR_MESSAGE} from "@app/pomade" import {getPomadeLoginFailureMessage, POMADE_NETWORK_ERROR_MESSAGE} from "@app/pomade"
@@ -73,16 +73,17 @@
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
{#each uniqBy(o => o.pubkey, options) as option (option.pubkey)} {#each uniqBy(o => o.pubkey, options) as option (option.pubkey)}
<Button <Button
variant="secondary"
onclick={() => selectAccount(option)} onclick={() => selectAccount(option)}
disabled={loading} disabled={loading}
class="card2 bg-alt flex w-full items-center p-3 text-left"> class="flex w-full items-center p-3 text-left">
<Profile inert pubkey={option.pubkey} /> <Profile inert pubkey={option.pubkey} />
</Button> </Button>
{/each} {/each}
</div> </div>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back} disabled={loading}> <Button variant="ghost" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
+12 -11
View File
@@ -1,14 +1,15 @@
<script lang="ts"> <script lang="ts">
import {preventDefault} from "@lib/html" import {preventDefault} from "@lib/html"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components2/Spinner.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components2/ModalFooter.svelte"
import Text from "@lib/components2/Text.svelte"
import {logout} from "@app/session" import {logout} from "@app/session"
const back = () => history.back() const back = () => history.back()
@@ -32,14 +33,14 @@
<ModalHeader> <ModalHeader>
<ModalTitle>Are you sure you want<br />to log out?</ModalTitle> <ModalTitle>Are you sure you want<br />to log out?</ModalTitle>
</ModalHeader> </ModalHeader>
<p class="text-center">Your local database will be cleared.</p> <Text class="text-center">Your local database will be cleared.</Text>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button variant="ghost" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
<Button type="submit" class="btn btn-primary" disabled={loading}> <Button type="submit" variant="primary" disabled={loading}>
<Spinner {loading}>Log Out</Spinner> <Spinner {loading}>Log Out</Spinner>
</Button> </Button>
</ModalFooter> </ModalFooter>
+14 -13
View File
@@ -6,11 +6,12 @@
import Shield from "@assets/icons/shield-minimalistic.svg?dataurl" import Shield from "@assets/icons/shield-minimalistic.svg?dataurl"
import Bell from "@assets/icons/bell.svg?dataurl" import Bell from "@assets/icons/bell.svg?dataurl"
import Wallet from "@assets/icons/wallet.svg?dataurl" import Wallet from "@assets/icons/wallet.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components2/Link.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import Grid from "@lib/components2/Grid.svelte"
import Profile from "@app/components/Profile.svelte" import Profile from "@app/components/Profile.svelte"
import LogOut from "@app/components/LogOut.svelte" import LogOut from "@app/components/LogOut.svelte"
import {pushModal} from "@app/modal" import {pushModal} from "@app/modal"
@@ -28,11 +29,11 @@
<Profile inert pubkey={$pubkey} /> <Profile inert pubkey={$pubkey} />
</Link> </Link>
{/if} {/if}
<div class="grid grid-cols-3 gap-3 w-full"> <Grid cols={3} gap={3} class="w-full">
<Link <Link
replaceState replaceState
href="/settings/alerts" href="/settings/alerts"
class="aspect-square btn h-[unset] btn-neutral flex flex-col gap-2 text-center"> class="clay-card clay-card-sm clay-card-interactive aspect-square flex flex-col gap-2 items-center justify-center text-center p-3 cl-text">
<Icon icon={Bell} size={5} /> <Icon icon={Bell} size={5} />
Alerts Alerts
</Link> </Link>
@@ -40,7 +41,7 @@
<Link <Link
replaceState replaceState
href="/settings/wallet" href="/settings/wallet"
class="aspect-square btn h-[unset] btn-neutral flex flex-col gap-2 text-center"> class="clay-card clay-card-sm clay-card-interactive aspect-square flex flex-col gap-2 items-center justify-center text-center p-3 cl-text">
<Icon icon={Wallet} size={5} /> <Icon icon={Wallet} size={5} />
Wallet Wallet
</Link> </Link>
@@ -48,29 +49,29 @@
<Link <Link
replaceState replaceState
href="/settings/relays" href="/settings/relays"
class="aspect-square btn h-[unset] btn-neutral flex flex-col gap-2 text-center"> class="clay-card clay-card-sm clay-card-interactive aspect-square flex flex-col gap-2 items-center justify-center text-center p-3 cl-text">
<Icon icon={Server} size={5} /> <Icon icon={Server} size={5} />
Relays Relays
</Link> </Link>
<Link <Link
replaceState replaceState
href="/settings/content" href="/settings/content"
class="aspect-square btn h-[unset] btn-neutral flex flex-col gap-2 text-center"> class="clay-card clay-card-sm clay-card-interactive aspect-square flex flex-col gap-2 items-center justify-center text-center p-3 cl-text">
<Icon icon={GalleryMinimalistic} size={5} /> <Icon icon={GalleryMinimalistic} size={5} />
Content Content
</Link> </Link>
<Link <Link
replaceState replaceState
href="/settings/privacy" href="/settings/privacy"
class="aspect-square btn h-[unset] btn-neutral flex flex-col gap-2 text-center"> class="clay-card clay-card-sm clay-card-interactive aspect-square flex flex-col gap-2 items-center justify-center text-center p-3 cl-text">
<Icon icon={Shield} size={5} /> <Icon icon={Shield} size={5} />
Privacy Privacy
</Link> </Link>
</div> </Grid>
<div class="flex gap-3 items-center opacity-75 text-sm"> <div class="flex gap-3 items-center opacity-75 text-sm">
<Button onclick={toggleTheme}>Theme</Button> <Button onclick={toggleTheme}>Theme</Button>
/ /
<Link replaceState href="/settings/about">About</Link> <Link replaceState styled href="/settings/about">About</Link>
/ /
<Button onclick={logout}>Log Out</Button> <Button onclick={logout}>Log Out</Button>
</div> </div>
+2 -2
View File
@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import {onMount, mount, unmount} from "svelte" import {onMount, mount, unmount} from "svelte"
import Drawer from "@lib/components/Drawer.svelte" import Drawer from "@lib/components2/Drawer.svelte"
import Dialog from "@lib/components/Dialog.svelte" import Dialog from "@lib/components2/Dialog.svelte"
import {modal, modalStack, popModal} from "@app/modal" import {modal, modalStack, popModal} from "@app/modal"
const closeModal = () => { const closeModal = () => {
+6 -5
View File
@@ -4,8 +4,9 @@
import {formatTimestamp} from "@welshman/lib" import {formatTimestamp} from "@welshman/lib"
import type {TrustedEvent} from "@welshman/util" import type {TrustedEvent} from "@welshman/util"
import Danger from "@assets/icons/danger-triangle.svg?dataurl" import Danger from "@assets/icons/danger-triangle.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Row from "@lib/components2/Row.svelte"
import Profile from "@app/components/Profile.svelte" import Profile from "@app/components/Profile.svelte"
import ProfileName from "@app/components/ProfileName.svelte" import ProfileName from "@app/components/ProfileName.svelte"
import {goToEvent} from "@app/routes" import {goToEvent} from "@app/routes"
@@ -39,11 +40,11 @@
<div class="flex flex-col gap-2 {restProps.class}" class:shadow-md={!noShadow}> <div class="flex flex-col gap-2 {restProps.class}" class:shadow-md={!noShadow}>
{#if muted} {#if muted}
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<div class="row-2 relative"> <Row class="relative">
<Icon icon={Danger} class="mt-1" /> <Icon icon={Danger} class="mt-1" />
<p>You have muted this person.</p> <p>You have muted this person.</p>
</div> </Row>
<Button class="link ml-8" onclick={ignoreMute}>Show anyway</Button> <Button class="cl-link ml-8" onclick={ignoreMute}>Show anyway</Button>
</div> </div>
{:else} {:else}
<div class="flex items-start justify-between gap-2"> <div class="flex items-start justify-between gap-2">
@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import type {ComponentProps} from "svelte" import type {ComponentProps} from "svelte"
import {getTag, getTagValue, getTagValues} from "@welshman/util" import {getTag, getTagValue, getTagValues} from "@welshman/util"
import CurrencySymbol from "@lib/components/CurrencySymbol.svelte" import CurrencySymbol from "@lib/components2/CurrencySymbol.svelte"
import Content from "@app/components/Content.svelte" import Content from "@app/components/Content.svelte"
import ContentLinkBlock from "@app/components/ContentLinkBlock.svelte" import ContentLinkBlock from "@app/components/ContentLinkBlock.svelte"
@@ -11,8 +11,8 @@
<CalendarEventDate event={props.event} /> <CalendarEventDate event={props.event} />
<div class="flex grow flex-col"> <div class="flex grow flex-col">
<CalendarEventHeader event={props.event} /> <CalendarEventHeader event={props.event} />
<div class="flex py-2 opacity-50"> <div class="flex py-2">
<div class="h-px grow bg-base-content opacity-25"></div> <div class="cl-divider-soft grow"></div>
</div> </div>
<Content {...props} /> <Content {...props} />
</div> </div>
@@ -7,7 +7,10 @@
formatTimestampAsTime, formatTimestampAsTime,
} from "@welshman/lib" } from "@welshman/lib"
import ClockCircle from "@assets/icons/clock-circle.svg?dataurl" import ClockCircle from "@assets/icons/clock-circle.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Col from "@lib/components2/Col.svelte"
import Row from "@lib/components2/Row.svelte"
import Text from "@lib/components2/Text.svelte"
import ContentMinimal from "@app/components/ContentMinimal.svelte" import ContentMinimal from "@app/components/ContentMinimal.svelte"
const props: ComponentProps<typeof ContentMinimal> = $props() const props: ComponentProps<typeof ContentMinimal> = $props()
@@ -16,21 +19,21 @@
const end = $derived(parseInt(meta.end)) const end = $derived(parseInt(meta.end))
</script> </script>
<div class="flex flex-col"> <Col>
<div class="flex grow flex-wrap justify-between gap-2"> <div class="flex grow flex-wrap justify-between gap-2">
<p class="text-sm">{meta.title || meta.name}</p> <Text size="sm">{meta.title || meta.name}</Text>
{#if !isNaN(start) && !isNaN(end)} {#if !isNaN(start) && !isNaN(end)}
{@const startDateDisplay = formatTimestampAsDate(start)} {@const startDateDisplay = formatTimestampAsDate(start)}
{@const endDateDisplay = formatTimestampAsDate(end)} {@const endDateDisplay = formatTimestampAsDate(end)}
{@const isSingleDay = startDateDisplay === endDateDisplay} {@const isSingleDay = startDateDisplay === endDateDisplay}
<div class="flex items-center gap-2"> <Row>
<Icon icon={ClockCircle} size={4} /> <Icon icon={ClockCircle} size={4} />
<span class="hidden sm:block">{formatTimestampAsDate(start)}</span> <span class="hidden sm:block">{formatTimestampAsDate(start)}</span>
{formatTimestampAsTime(start)}{isSingleDay {formatTimestampAsTime(start)}{isSingleDay
? formatTimestampAsTime(end) ? formatTimestampAsTime(end)
: formatTimestamp(end)} : formatTimestamp(end)}
</div> </Row>
{/if} {/if}
</div> </div>
<ContentMinimal {...props} /> <ContentMinimal {...props} />
</div> </Col>
@@ -6,7 +6,9 @@
import {deriveItemsByKey, deriveArray} from "@welshman/store" import {deriveItemsByKey, deriveArray} from "@welshman/store"
import {repository, getValidZap} from "@welshman/app" import {repository, getValidZap} from "@welshman/app"
import Bolt from "@assets/icons/bolt.svg?dataurl" import Bolt from "@assets/icons/bolt.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Row from "@lib/components2/Row.svelte"
import Text from "@lib/components2/Text.svelte"
import ContentMinimal from "@app/components/ContentMinimal.svelte" import ContentMinimal from "@app/components/ContentMinimal.svelte"
const props: ComponentProps<typeof ContentMinimal> = $props() const props: ComponentProps<typeof ContentMinimal> = $props()
@@ -29,9 +31,9 @@
<div class="flex justify-between"> <div class="flex justify-between">
<span class="text-sm">{props.event.content}</span> <span class="text-sm">{props.event.content}</span>
<div class="flex items-center gap-1"> <Row gap={1}>
<Icon icon={Bolt} size={4} /> <Icon icon={Bolt} size={4} />
{zapAmount}/{goalAmount} sats funded {zapAmount}/{goalAmount} sats funded
</div> </Row>
</div> </div>
<ContentMinimal {...props} event={fakeEvent} /> <ContentMinimal {...props} event={fakeEvent} />
@@ -3,6 +3,8 @@
import {derived} from "svelte/store" import {derived} from "svelte/store"
import {POLL_RESPONSE} from "@welshman/util" import {POLL_RESPONSE} from "@welshman/util"
import ContentMinimal from "@app/components/ContentMinimal.svelte" import ContentMinimal from "@app/components/ContentMinimal.svelte"
import Col from "@lib/components2/Col.svelte"
import Text from "@lib/components2/Text.svelte"
import {deriveEvents} from "@app/repository" import {deriveEvents} from "@app/repository"
import {getPollResults} from "@app/polls" import {getPollResults} from "@app/polls"
@@ -13,7 +15,7 @@
const results = derived(responses, $responses => getPollResults(props.event, $responses)) const results = derived(responses, $responses => getPollResults(props.event, $responses))
</script> </script>
<div class="flex flex-col gap-0"> <Col gap={0}>
<ContentMinimal {...props} /> <ContentMinimal {...props} />
<span class="text-xs opacity-50">{$results.voters} voter{$results.voters === 1 ? "" : "s"}</span> <Text size="xs" subtle>{$results.voters} voter{$results.voters === 1 ? "" : "s"}</Text>
</div> </Col>
@@ -2,6 +2,7 @@
import type {ComponentProps} from "svelte" import type {ComponentProps} from "svelte"
import {getTagValue} from "@welshman/util" import {getTagValue} from "@welshman/util"
import ContentMinimal from "@app/components/ContentMinimal.svelte" import ContentMinimal from "@app/components/ContentMinimal.svelte"
import Text from "@lib/components2/Text.svelte"
const props: ComponentProps<typeof ContentMinimal> = $props() const props: ComponentProps<typeof ContentMinimal> = $props()
@@ -9,7 +10,7 @@
</script> </script>
{#if title} {#if title}
<span class="text-sm">{title}</span> <Text size="sm">{title}</Text>
{/if} {/if}
{#if props.event.content} {#if props.event.content}
<ContentMinimal {...props} /> <ContentMinimal {...props} />
+3 -2
View File
@@ -5,6 +5,7 @@
import {POLL_RESPONSE} from "@welshman/util" import {POLL_RESPONSE} from "@welshman/util"
import PollVotes from "@app/components/PollVotes.svelte" import PollVotes from "@app/components/PollVotes.svelte"
import Content from "@app/components/Content.svelte" import Content from "@app/components/Content.svelte"
import Col from "@lib/components2/Col.svelte"
const props: ComponentProps<typeof Content> = $props() const props: ComponentProps<typeof Content> = $props()
@@ -20,10 +21,10 @@
}) })
</script> </script>
<div class="flex flex-col gap-3"> <Col gap={3}>
<Content event={props.event} showEntire url={props.url} /> <Content event={props.event} showEntire url={props.url} />
{#if props.url} {#if props.url}
<PollVotes url={props.url} event={props.event} /> <PollVotes url={props.url} event={props.event} />
{/if} {/if}
</div> </Col>
+5 -3
View File
@@ -2,17 +2,19 @@
import type {ComponentProps} from "svelte" import type {ComponentProps} from "svelte"
import {getTagValue} from "@welshman/util" import {getTagValue} from "@welshman/util"
import Content from "@app/components/Content.svelte" import Content from "@app/components/Content.svelte"
import Col from "@lib/components2/Col.svelte"
import Text from "@lib/components2/Text.svelte"
const props: ComponentProps<typeof Content> = $props() const props: ComponentProps<typeof Content> = $props()
const title = getTagValue("title", props.event.tags) const title = getTagValue("title", props.event.tags)
</script> </script>
<div class="flex flex-col gap-2"> <Col gap={2}>
{#if title} {#if title}
<p class="text-xl">{title}</p> <Text size="xl">{title}</Text>
{/if} {/if}
{#if props.event.content} {#if props.event.content}
<Content {...props} /> <Content {...props} />
{/if} {/if}
</div> </Col>
+5 -5
View File
@@ -4,8 +4,8 @@
import type {TrustedEvent, EventContent} from "@welshman/util" import type {TrustedEvent, EventContent} from "@welshman/util"
import {Router} from "@welshman/router" import {Router} from "@welshman/router"
import SmileCircle from "@assets/icons/smile-circle.svg?dataurl" import SmileCircle from "@assets/icons/smile-circle.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import EmojiButton from "@lib/components/EmojiButton.svelte" import EmojiButton from "@lib/components2/EmojiButton.svelte"
import NoteContent from "@app/components/NoteContent.svelte" import NoteContent from "@app/components/NoteContent.svelte"
import NoteCard from "@app/components/NoteCard.svelte" import NoteCard from "@app/components/NoteCard.svelte"
import ReactionSummary from "@app/components/ReactionSummary.svelte" import ReactionSummary from "@app/components/ReactionSummary.svelte"
@@ -40,11 +40,11 @@
}) })
</script> </script>
<NoteCard {event} {url} class="cv card2 bg-alt"> <NoteCard {event} {url} class="cv clay-card cl-surface-alt p-4">
<NoteContent {event} expandMode="inline" /> <NoteContent {event} expandMode="inline" />
<div class="flex w-full justify-between gap-2"> <div class="flex w-full justify-between gap-2">
<ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="tooltip-right"> <ReactionSummary {url} {event} {deleteReaction} {createReaction} reactionClass="cl-tip-right">
<EmojiButton {onEmoji} class="btn btn-neutral btn-xs h-[26px] rounded-box"> <EmojiButton {onEmoji} variant="secondary" size="sm" circle>
<Icon icon={SmileCircle} size={4} /> <Icon icon={SmileCircle} size={4} />
</EmojiButton> </EmojiButton>
</ReactionSummary> </ReactionSummary>
+12 -12
View File
@@ -5,16 +5,16 @@
import {preventDefault} from "@lib/html" import {preventDefault} from "@lib/html"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components2/Spinner.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components2/ModalFooter.svelte"
import StringMultiInput from "@lib/components/StringMultiInput.svelte" import StringMultiInput from "@lib/components2/StringMultiInput.svelte"
import PasswordResetConfirm from "@app/components/PasswordResetConfirm.svelte" import PasswordResetConfirm from "@app/components/PasswordResetConfirm.svelte"
import {pushToast} from "@app/toast" import {pushToast} from "@app/toast"
import {pushModal} from "@app/modal" import {pushModal} from "@app/modal"
@@ -94,11 +94,11 @@
<StringMultiInput bind:value={otps} placeholder="Enter your confirmation codes..." /> <StringMultiInput bind:value={otps} placeholder="Enter your confirmation codes..." />
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button variant="ghost" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
<Button type="submit" class="btn btn-primary" disabled={loading || otps.length < 2}> <Button type="submit" variant="primary" disabled={loading || otps.length < 2}>
<Spinner {loading}>Continue</Spinner> <Spinner {loading}>Continue</Spinner>
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
+13 -13
View File
@@ -6,16 +6,16 @@
import Key from "@assets/icons/key.svg?dataurl" import Key from "@assets/icons/key.svg?dataurl"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import FieldInline from "@lib/components/FieldInline.svelte" import FieldInline from "@lib/components2/FieldInline.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components2/Spinner.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components2/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components2/ModalFooter.svelte"
import {loginWithPomade, deleteCurrentPomadeSession} from "@app/pomade" import {loginWithPomade, deleteCurrentPomadeSession} from "@app/pomade"
import {clearModals} from "@app/modal" import {clearModals} from "@app/modal"
import {pushToast} from "@app/toast" import {pushToast} from "@app/toast"
@@ -98,7 +98,7 @@
<p>New Password*</p> <p>New Password*</p>
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<label class="input input-bordered flex w-full items-center gap-2"> <label class="input-cl input-cl-group w-full">
<Icon icon={Key} /> <Icon icon={Key} />
<input type="password" bind:value={password} /> <input type="password" bind:value={password} />
</label> </label>
@@ -106,11 +106,11 @@
</FieldInline> </FieldInline>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button variant="ghost" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
<Button class="btn btn-primary" type="submit" disabled={loading || !password}> <Button variant="primary" type="submit" disabled={loading || !password}>
<Spinner {loading}>Continue</Spinner> <Spinner {loading}>Continue</Spinner>
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
+18 -14
View File
@@ -1,7 +1,9 @@
<script lang="ts"> <script lang="ts">
import UserCircle from "@assets/icons/user-circle.svg?dataurl" import UserCircle from "@assets/icons/user-circle.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Card from "@lib/components2/Card.svelte"
import Col from "@lib/components2/Col.svelte"
import Profile from "@app/components/Profile.svelte" import Profile from "@app/components/Profile.svelte"
import ProfileInfo from "@app/components/ProfileInfo.svelte" import ProfileInfo from "@app/components/ProfileInfo.svelte"
import ProfileBadges from "@app/components/ProfileBadges.svelte" import ProfileBadges from "@app/components/ProfileBadges.svelte"
@@ -18,18 +20,20 @@
const openProfile = () => pushModal(ProfileDetail, {pubkey, url}) const openProfile = () => pushModal(ProfileDetail, {pubkey, url})
</script> </script>
<div class="card2 bg-alt flex flex-col gap-4 shadow-md"> <Card>
<div class="flex justify-between"> <Col gap={4}>
<Profile {pubkey} {url} /> <div class="flex justify-between">
<Button onclick={openProfile} class="btn btn-primary hidden sm:flex"> <Profile {pubkey} {url} />
<Button onclick={openProfile} variant="primary" class="hidden sm:flex">
<Icon icon={UserCircle} />
View Profile
</Button>
</div>
<ProfileInfo {pubkey} {url} />
<ProfileBadges {pubkey} {url} />
<Button onclick={openProfile} variant="primary" class="sm:hidden">
<Icon icon={UserCircle} /> <Icon icon={UserCircle} />
View Profile View Profile
</Button> </Button>
</div> </Col>
<ProfileInfo {pubkey} {url} /> </Card>
<ProfileBadges {pubkey} {url} />
<Button onclick={openProfile} class="btn btn-primary sm:hidden">
<Icon icon={UserCircle} />
View Profile
</Button>
</div>
+39 -41
View File
@@ -7,18 +7,22 @@
import HamburgerMenu from "@assets/icons/hamburger-menu.svg?dataurl" import HamburgerMenu from "@assets/icons/hamburger-menu.svg?dataurl"
import PlusCircle from "@assets/icons/add-circle.svg?dataurl" import PlusCircle from "@assets/icons/add-circle.svg?dataurl"
import MinusCircle from "@assets/icons/minus-circle.svg?dataurl" import MinusCircle from "@assets/icons/minus-circle.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Field from "@lib/components/Field.svelte" import Col from "@lib/components2/Col.svelte"
import FieldInline from "@lib/components/FieldInline.svelte" import Row from "@lib/components2/Row.svelte"
import DateTimeInput from "@lib/components/DateTimeInput.svelte" import Field from "@lib/components2/Field.svelte"
import Button from "@lib/components/Button.svelte" import FieldInline from "@lib/components2/FieldInline.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Input from "@lib/components2/Input.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import Select from "@lib/components2/Select.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte" import DateTimeInput from "@lib/components2/DateTimeInput.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte" import Button from "@lib/components2/Button.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import Spinner from "@lib/components2/Spinner.svelte"
import Modal from "@lib/components/Modal.svelte" import ModalHeader from "@lib/components2/ModalHeader.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalTitle from "@lib/components2/ModalTitle.svelte"
import ModalSubtitle from "@lib/components2/ModalSubtitle.svelte"
import ModalFooter from "@lib/components2/ModalFooter.svelte"
import Modal from "@lib/components2/Modal.svelte"
import ModalBody from "@lib/components2/ModalBody.svelte"
import {pushToast} from "@app/toast" import {pushToast} from "@app/toast"
import {PROTECTED, publishRoomQuote} from "@app/groups" import {PROTECTED, publishRoomQuote} from "@app/groups"
import {canEnforceNip70} from "@app/relays" import {canEnforceNip70} from "@app/relays"
@@ -188,21 +192,18 @@
<ModalTitle>Create a Poll</ModalTitle> <ModalTitle>Create a Poll</ModalTitle>
<ModalSubtitle>Ask a question and collect votes right in the feed.</ModalSubtitle> <ModalSubtitle>Ask a question and collect votes right in the feed.</ModalSubtitle>
</ModalHeader> </ModalHeader>
<div class="col-8 relative"> <Col gap={8} class="relative">
<Field> <Field>
{#snippet label()} {#snippet label()}
<p>Question*</p> <p>Question*</p>
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<label class="input input-bordered flex w-full items-center gap-2"> <!-- svelte-ignore a11y_autofocus -->
<!-- svelte-ignore a11y_autofocus --> <Input
<input autofocus={!isMobile}
autofocus={!isMobile} bind:value={title}
bind:value={title} type="text"
class="grow" placeholder="What would you like to ask?" />
type="text"
placeholder="What would you like to ask?" />
</label>
{/snippet} {/snippet}
</Field> </Field>
@@ -211,7 +212,7 @@
<p>Options*</p> <p>Options*</p>
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<div class="flex flex-col gap-2" role="list"> <Col gap={2} role="list">
{#each options as option, index (option.id)} {#each options as option, index (option.id)}
<div <div
class="flex items-center gap-2" class="flex items-center gap-2"
@@ -224,37 +225,34 @@
<div class="cursor-move opacity-70" aria-label="Drag handle"> <div class="cursor-move opacity-70" aria-label="Drag handle">
<Icon icon={HamburgerMenu} size={4} /> <Icon icon={HamburgerMenu} size={4} />
</div> </div>
<label class="input input-bordered flex w-full items-center gap-2"> <Input
<input value={option.value}
value={option.value} type="text"
class="grow" placeholder={`Option ${index + 1}`}
type="text" oninput={e => updateOption(option.id, e.currentTarget.value)} />
placeholder={`Option ${index + 1}`} <Button variant="ghost" size="sm" onclick={() => removeOption(option.id)}>
oninput={e => updateOption(option.id, e.currentTarget.value)} />
</label>
<Button class="btn btn-ghost btn-sm" onclick={() => removeOption(option.id)}>
<Icon icon={MinusCircle} size={4} /> <Icon icon={MinusCircle} size={4} />
</Button> </Button>
</div> </div>
{/each} {/each}
<Button class="btn btn-outline btn-sm self-end" onclick={addOption}> <Button variant="secondary" size="sm" class="self-end" onclick={addOption}>
<Icon icon={PlusCircle} size={4} /> <Icon icon={PlusCircle} size={4} />
Add option Add option
</Button> </Button>
</div> </Col>
{/snippet} {/snippet}
</Field> </Field>
<div class="flex flex-col gap-2"> <Col gap={2}>
<FieldInline> <FieldInline>
{#snippet label()} {#snippet label()}
Poll type Poll type
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<select class="select select-bordered w-full max-w-xs" bind:value={pollType}> <Select class="w-full max-w-xs" bind:value={pollType}>
<option value="singlechoice">Single choice</option> <option value="singlechoice">Single choice</option>
<option value="multiplechoice">Multiple choice</option> <option value="multiplechoice">Multiple choice</option>
</select> </Select>
{/snippet} {/snippet}
</FieldInline> </FieldInline>
<FieldInline> <FieldInline>
@@ -265,15 +263,15 @@
<DateTimeInput bind:value={endsAt} /> <DateTimeInput bind:value={endsAt} />
{/snippet} {/snippet}
</FieldInline> </FieldInline>
</div> </Col>
</div> </Col>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back} disabled={loading}> <Button variant="ghost" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
<Button type="submit" class="btn btn-primary" disabled={loading}> <Button type="submit" variant="primary" disabled={loading}>
<Spinner {loading}>Create Poll</Spinner> <Spinner {loading}>Create Poll</Spinner>
</Button> </Button>
</ModalFooter> </ModalFooter>
+16 -14
View File
@@ -1,7 +1,9 @@
<script lang="ts"> <script lang="ts">
import type {TrustedEvent} from "@welshman/util" import type {TrustedEvent} from "@welshman/util"
import {getTagValue} from "@welshman/util" import {getTagValue} from "@welshman/util"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components2/Link.svelte"
import Col from "@lib/components2/Col.svelte"
import Text from "@lib/components2/Text.svelte"
import NoteContent from "@app/components/NoteContent.svelte" import NoteContent from "@app/components/NoteContent.svelte"
import CommentActions from "@app/components/CommentActions.svelte" import CommentActions from "@app/components/CommentActions.svelte"
import RoomLink from "@app/components/RoomLink.svelte" import RoomLink from "@app/components/RoomLink.svelte"
@@ -18,17 +20,17 @@
const h = getTagValue("h", event.tags) const h = getTagValue("h", event.tags)
</script> </script>
<Link <Link class="clay-card w-full cursor-pointer p-4 sm:p-6" href={makePollPath(url, event.id)}>
class="cv col-2 card2 bg-alt w-full cursor-pointer shadow-md" <Col>
href={makePollPath(url, event.id)}> <NoteContent {event} {url} />
<NoteContent {event} {url} /> <div class="flex w-full flex-col items-end justify-between gap-2 sm:flex-row">
<div class="flex w-full flex-col items-end justify-between gap-2 sm:flex-row"> <Text size="sm" muted class="whitespace-nowrap py-1">
<span class="whitespace-nowrap py-1 text-sm opacity-75"> Posted by <ProfileLink pubkey={event.pubkey} {url} />
Posted by <ProfileLink pubkey={event.pubkey} {url} /> {#if h}
{#if h} in <RoomLink {url} {h} />
in <RoomLink {url} {h} /> {/if}
{/if} </Text>
</span> <CommentActions segment="polls" showActivity {url} {event} />
<CommentActions segment="polls" showActivity {url} {event} /> </div>
</div> </Col>
</Link> </Link>
+16 -7
View File
@@ -2,6 +2,9 @@
import {tweened} from "svelte/motion" import {tweened} from "svelte/motion"
import type {TrustedEvent} from "@welshman/util" import type {TrustedEvent} from "@welshman/util"
import {noop} from "@welshman/lib" import {noop} from "@welshman/lib"
import Row from "@lib/components2/Row.svelte"
import Col from "@lib/components2/Col.svelte"
import Text from "@lib/components2/Text.svelte"
import {stopPropagation} from "@lib/html" import {stopPropagation} from "@lib/html"
import {getPollType, isPollClosed} from "@app/polls" import {getPollType, isPollClosed} from "@app/polls"
@@ -41,7 +44,7 @@
}) })
</script> </script>
<div class="flex flex-col gap-2 card2 card2-sm bg-alt"> <Col class="clay-card clay-card-sm cl-surface-alt p-3">
<div class="flex items-center justify-between gap-2"> <div class="flex items-center justify-between gap-2">
<label class="flex min-w-0 grow items-center gap-2"> <label class="flex min-w-0 grow items-center gap-2">
{#if !closed} {#if !closed}
@@ -49,22 +52,28 @@
<input <input
name={event.id} name={event.id}
type="radio" type="radio"
class="radio radio-primary radio-sm" class="h-4 w-4 shrink-0"
style="accent-color: var(--cl-primary)"
checked={selected} checked={selected}
onclick={stopPropagation(noop)} onclick={stopPropagation(noop)}
onchange={onselect} /> onchange={onselect} />
{:else} {:else}
<input <input
type="checkbox" type="checkbox"
class="checkbox checkbox-primary checkbox-sm" class="h-4 w-4 shrink-0"
style="accent-color: var(--cl-primary)"
checked={selected} checked={selected}
onclick={stopPropagation(noop)} onclick={stopPropagation(noop)}
onchange={onselect} /> onchange={onselect} />
{/if} {/if}
{/if} {/if}
<span class="truncate">{option.label}</span> <span class="cl-text truncate">{option.label}</span>
</label> </label>
<span class="whitespace-nowrap text-xs opacity-75">{votes} vote{votes === 1 ? "" : "s"}</span> <Text size="sm" muted class="whitespace-nowrap">{votes} vote{votes === 1 ? "" : "s"}</Text>
</div> </div>
<progress class="progress progress-primary" value={$tweenedVotes} max={$tweenedMax}></progress> <progress
</div> class="h-2 w-full overflow-hidden"
style="accent-color: var(--cl-primary); border-radius: var(--cl-r-pill)"
value={$tweenedVotes}
max={$tweenedMax}></progress>
</Col>
+10 -7
View File
@@ -8,6 +8,9 @@
import {pushToast} from "@app/toast" import {pushToast} from "@app/toast"
import {makePollResponse} from "@app/polls" import {makePollResponse} from "@app/polls"
import PollOption from "@app/components/PollOption.svelte" import PollOption from "@app/components/PollOption.svelte"
import Col from "@lib/components2/Col.svelte"
import Row from "@lib/components2/Row.svelte"
import Text from "@lib/components2/Text.svelte"
import { import {
getPollEndsAt, getPollEndsAt,
getPollOptions, getPollOptions,
@@ -107,12 +110,12 @@
}) })
</script> </script>
<div class="flex flex-col gap-2"> <Col gap={2}>
{#each options as option (option.id)} {#each options as option (option.id)}
<PollOption {event} {option} {results} {selectedIds} {setSingleChoice} {toggleMultipleChoice} /> <PollOption {event} {option} {results} {selectedIds} {setSingleChoice} {toggleMultipleChoice} />
{/each} {/each}
<div class="flex flex-wrap items-center justify-between gap-2"> <Row gap={2} class="flex-wrap justify-between">
<div class="text-sm opacity-75"> <Text muted size="sm">
{pollType === "multiplechoice" ? "Multiple choice" : "Single choice"} {pollType === "multiplechoice" ? "Multiple choice" : "Single choice"}
{#if endsAt} {#if endsAt}
{#if closed} {#if closed}
@@ -121,7 +124,7 @@
• Ends {formatTimestampRelative(endsAt)} • Ends {formatTimestampRelative(endsAt)}
{/if} {/if}
{/if} {/if}
</div> </Text>
<div class="text-sm opacity-75">{results.voters} vote{results.voters === 1 ? "" : "s"}</div> <Text muted size="sm">{results.voters} vote{results.voters === 1 ? "" : "s"}</Text>
</div> </Row>
</div> </Col>
+29 -30
View File
@@ -4,9 +4,12 @@
import {session, isPomadeSession} from "@welshman/app" import {session, isPomadeSession} from "@welshman/app"
import MenuDots from "@assets/icons/menu-dots.svg?dataurl" import MenuDots from "@assets/icons/menu-dots.svg?dataurl"
import {fly} from "@lib/transition" import {fly} from "@lib/transition"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components2/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components2/Button.svelte"
import Popover from "@lib/components/Popover.svelte" import Popover from "@lib/components2/Popover.svelte"
import Badge from "@lib/components2/Badge.svelte"
import Row from "@lib/components2/Row.svelte"
import Col from "@lib/components2/Col.svelte"
import TrashBin2 from "@assets/icons/trash-bin-2.svg?dataurl" import TrashBin2 from "@assets/icons/trash-bin-2.svg?dataurl"
import {pushToast} from "@app/toast" import {pushToast} from "@app/toast"
import {loadOtherPomadeSessions} from "@app/pomade" import {loadOtherPomadeSessions} from "@app/pomade"
@@ -69,50 +72,46 @@
</script> </script>
{#if sessions.length > 0} {#if sessions.length > 0}
<div class="flex flex-col gap-4 border-t border-solid border-base-100 pt-4"> <Col gap={4} class="cl-border-t pt-4">
<strong>Other Sessions</strong> <strong>Other Sessions</strong>
{#each sessions as sessionItem (sessionItem.client)} {#each sessions as sessionItem (sessionItem.client)}
<div class="flex flex-col gap-2"> <Col gap={2}>
<div class="flex justify-between items-center"> <Row class="justify-between">
<div class="flex gap-3 items-center text-sm"> <Row gap={3} class="text-sm">
<span>Session {sessionItem.client.slice(0, 8)}</span> <span>Session {sessionItem.client.slice(0, 8)}</span>
<span class="opacity-75"> <span class="cl-text-subtle">
{#if sessionItem.deactivated_at} {#if sessionItem.deactivated_at}
Deactivated Deactivated
{/if} {/if}
</span> </span>
</div> </Row>
<div class="relative"> <div class="relative">
<Button <Button circle size="sm" onclick={() => toggleMenu(sessionItem.client)}>
class="btn btn-circle btn-ghost btn-sm"
onclick={() => toggleMenu(sessionItem.client)}>
<Icon icon={MenuDots} /> <Icon icon={MenuDots} />
</Button> </Button>
{#if menuClient === sessionItem.client} {#if menuClient === sessionItem.client}
<Popover hideOnClick onClose={closeMenu}> <Popover hideOnClick onClose={closeMenu}>
<ul <div
transition:fly transition:fly
class="menu absolute right-0 z-popover mt-2 w-48 gap-1 rounded-box bg-base-100 p-2 shadow-md"> class="clay-card absolute right-0 z-popover mt-2 w-48 p-2">
<li> <Button block class="justify-start" onclick={() => deleteSession(sessionItem)}>
<Button onclick={() => deleteSession(sessionItem)}> <Icon icon={TrashBin2} />
<Icon icon={TrashBin2} /> Delete Session
Delete Session </Button>
</Button> </div>
</li>
</ul>
</Popover> </Popover>
{/if} {/if}
</div> </div>
</div> </Row>
<div class="flex gap-1"> <Row gap={1}>
<div class="badge badge-neutral"> <Badge variant="neutral">
Created {formatDate(sessionItem.created_at)} Created {formatDate(sessionItem.created_at)}
</div> </Badge>
<div class="badge badge-neutral"> <Badge variant="neutral">
Active {formatDate(sessionItem.last_activity)} Active {formatDate(sessionItem.last_activity)}
</div> </Badge>
</div> </Row>
</div> </Col>
{/each} {/each}
</div> </Col>
{/if} {/if}

Some files were not shown because too many files have changed in this diff Show More