Clean up modals

This commit is contained in:
Jon Staab
2026-02-10 11:39:29 -08:00
parent 7566f56858
commit 72f2effda4
15 changed files with 398 additions and 323 deletions
+1 -1
View File
@@ -274,7 +274,7 @@
.input-editor, .input-editor,
.chat-editor, .chat-editor,
.note-editor { .note-editor {
@apply -m-1 min-h-12 p-1; @apply -m-1 min-h-12 p-1 text-sm;
} }
.tiptap { .tiptap {
+2
View File
@@ -19,11 +19,13 @@
<ModalHeader> <ModalHeader>
<ModalTitle>People in this conversation</ModalTitle> <ModalTitle>People in this conversation</ModalTitle>
</ModalHeader> </ModalHeader>
<div class="flex flex-col gap-2">
{#each pubkeys as pubkey (pubkey)} {#each pubkeys as pubkey (pubkey)}
<div class="card2 bg-alt"> <div class="card2 bg-alt">
<Profile {pubkey} /> <Profile {pubkey} />
</div> </div>
{/each} {/each}
</div>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button> <Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button>
+2
View File
@@ -27,6 +27,7 @@
<Modal> <Modal>
<ModalBody> <ModalBody>
<div class="flex flex-col gap-2">
<Button class="btn btn-primary" onclick={startChat}> <Button class="btn btn-primary" onclick={startChat}>
<Icon size={5} icon={ChatSquare} /> <Icon size={5} icon={ChatSquare} />
Start chat Start chat
@@ -46,5 +47,6 @@
Enable alerts Enable alerts
</Button> </Button>
{/if} {/if}
</div>
</ModalBody> </ModalBody>
</Modal> </Modal>
@@ -49,6 +49,7 @@
<Modal> <Modal>
<ModalBody> <ModalBody>
<div class="flex flex-col gap-2">
<Button class="btn btn-neutral" onclick={showInfo}> <Button class="btn btn-neutral" onclick={showInfo}>
<Icon size={4} icon={Code2} /> <Icon size={4} icon={Code2} />
Message Info Message Info
@@ -65,5 +66,6 @@
<Icon size={4} icon={SmileCircle} /> <Icon size={4} icon={SmileCircle} />
Send Reaction Send Reaction
</Button> </Button>
</div>
</ModalBody> </ModalBody>
</Modal> </Modal>
+2
View File
@@ -25,6 +25,7 @@
<Modal> <Modal>
<ModalBody> <ModalBody>
<div class="flex flex-col gap-2">
<Link replaceState href="/settings/profile"> <Link replaceState href="/settings/profile">
<CardButton class="btn-neutral"> <CardButton class="btn-neutral">
{#snippet icon()} {#snippet icon()}
@@ -119,5 +120,6 @@
<Button onclick={logout} class="btn btn-neutral"> <Button onclick={logout} class="btn btn-neutral">
<Icon icon={Exit} /> Log Out <Icon icon={Exit} /> Log Out
</Button> </Button>
</div>
</ModalBody> </ModalBody>
</Modal> </Modal>
+4 -1
View File
@@ -3,11 +3,14 @@
type Props = { type Props = {
url: string url: string
class?: string
} }
const {url}: Props = $props() const {url, ...props}: Props = $props()
const display = $derived(deriveRelayDisplay(url)) const display = $derived(deriveRelayDisplay(url))
</script> </script>
<span class={props.class}>
{$display} {$display}
</span>
+87 -44
View File
@@ -7,6 +7,7 @@
import Pen from "@assets/icons/pen.svg?dataurl" import Pen from "@assets/icons/pen.svg?dataurl"
import TrashBin2 from "@assets/icons/trash-bin-2.svg?dataurl" import TrashBin2 from "@assets/icons/trash-bin-2.svg?dataurl"
import Login3 from "@assets/icons/login-3.svg?dataurl" import Login3 from "@assets/icons/login-3.svg?dataurl"
import MenuDots from "@assets/icons/menu-dots.svg?dataurl"
import ClockCircle from "@assets/icons/clock-circle.svg?dataurl" import ClockCircle from "@assets/icons/clock-circle.svg?dataurl"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import EyeClosed from "@assets/icons/eye-closed.svg?dataurl" import EyeClosed from "@assets/icons/eye-closed.svg?dataurl"
@@ -15,8 +16,10 @@
import Microphone from "@assets/icons/microphone.svg?dataurl" import Microphone from "@assets/icons/microphone.svg?dataurl"
import Bookmark from "@assets/icons/bookmark.svg?dataurl" import Bookmark from "@assets/icons/bookmark.svg?dataurl"
import VolumeLoud from "@assets/icons/volume-loud.svg?dataurl" import VolumeLoud from "@assets/icons/volume-loud.svg?dataurl"
import {fly} from "@lib/transition"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Popover from "@lib/components/Popover.svelte"
import Confirm from "@lib/components/Confirm.svelte" import Confirm from "@lib/components/Confirm.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components/ModalBody.svelte"
@@ -62,6 +65,14 @@
const back = () => history.back() const back = () => history.back()
const toggleMenu = () => {
showMenu = !showMenu
}
const closeMenu = () => {
showMenu = false
}
const startEdit = () => pushModal(RoomEdit, {url, h}) const startEdit = () => pushModal(RoomEdit, {url, h})
const handleLoading = async (f: (url: string, room: RoomMeta) => Thunk) => { const handleLoading = async (f: (url: string, room: RoomMeta) => Thunk) => {
@@ -115,6 +126,7 @@
}) })
let loading = $state(false) let loading = $state(false)
let showMenu = $state(false)
</script> </script>
<Modal> <Modal>
@@ -129,33 +141,99 @@
<span class="text-primary">{displayRelayUrl(url)}</span> <span class="text-primary">{displayRelayUrl(url)}</span>
</div> </div>
</div> </div>
<div class="grid grid-cols-2 gap-2"> <div class="relative">
<Button class="btn btn-circle btn-ghost btn-sm" onclick={toggleMenu}>
<Icon icon={MenuDots} />
</Button>
{#if showMenu}
<Popover hideOnClick onClose={closeMenu}>
<ul
transition:fly
class="bg-alt menu absolute right-0 z-popover w-48 gap-1 rounded-box p-2 shadow-md">
{#if $userIsAdmin}
<li>
<Button class="text-error" onclick={startDelete}>
<Icon icon={TrashBin2} />
Delete Room
</Button>
</li>
<li>
<Button onclick={startEdit}>
<Icon icon={Pen} />
Edit Room
</Button>
</li>
{:else if $membershipStatus === MembershipStatus.Initial}
<li>
<Button disabled={loading} onclick={join}>
{#if loading}
<span class="loading loading-spinner loading-sm"></span>
{:else}
<Icon icon={Login3} />
{/if}
Join member list
</Button>
</li>
{:else if $membershipStatus === MembershipStatus.Pending}
<li>
<Button>
<Icon icon={ClockCircle} />
Membership pending
</Button>
</li>
{:else}
<li>
<Button disabled={loading} onclick={leave}>
{#if loading}
<span class="loading loading-spinner loading-sm"></span>
{:else}
<Icon icon={Login3} />
{/if}
Leave member list
</Button>
</li>
{/if}
</ul>
</Popover>
{/if}
</div>
</div>
<div class="flex flex-col gap-2 card2 card2-sm bg-alt">
<strong class="text-lg">Room Permissions</strong>
<div class="flex gap-2 flex-wrap">
{#if $room?.isRestricted} {#if $room?.isRestricted}
<Button <Button
class="btn btn-neutral btn-sm tooltip tooltip-left" class="btn btn-neutral btn-xs rounded-full tooltip flex gap-2 items-center"
data-tip="Only members can send messages."> data-tip="Only members can send messages.">
<Icon size={4} icon={Microphone} /> <Icon size={4} icon={Microphone} /> Restricted
</Button> </Button>
{/if} {/if}
{#if $room?.isPrivate} {#if $room?.isPrivate}
<Button <Button
class="btn btn-neutral btn-sm tooltip tooltip-left" class="btn btn-neutral btn-xs rounded-full tooltip flex gap-2 items-center"
data-tip="Only members can view messages."> data-tip="Only members can view messages.">
<Icon size={4} icon={Lock} /> <Icon size={4} icon={Lock} /> Private
</Button> </Button>
{/if} {/if}
{#if $room?.isHidden} {#if $room?.isHidden}
<Button <Button
class="btn btn-neutral btn-sm tooltip tooltip-left" class="btn btn-neutral btn-xs rounded-full tooltip flex gap-2 items-center"
data-tip="This room is not visible to non-members."> data-tip="This room is not visible to non-members.">
<Icon size={4} icon={EyeClosed} /> <Icon size={4} icon={EyeClosed} /> Hidden
</Button> </Button>
{/if} {/if}
{#if $room?.isClosed} {#if $room?.isClosed}
<Button <Button
class="btn btn-neutral btn-sm tooltip tooltip-left" class="btn btn-neutral btn-xs rounded-full tooltip flex gap-2 items-center"
data-tip="Requests to join this room will be ignored."> data-tip="Requests to join this room will be ignored.">
<Icon size={4} icon={MinusCircle} /> <Icon size={4} icon={MinusCircle} /> Closed
</Button>
{/if}
{#if !$room?.isRestricted && !$room?.isPrivate && !$room?.isHidden && !$room?.isClosed}
<Button
class="btn btn-neutral btn-xs rounded-full tooltip flex gap-2 items-center"
data-tip="This room has no additional access controls.">
<Icon size={4} icon={MinusCircle} /> Public
</Button> </Button>
{/if} {/if}
</div> </div>
@@ -203,40 +281,5 @@
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
<div class="flex gap-2">
{#if $userIsAdmin}
<Button class="btn btn-outline btn-error" onclick={startDelete}>
<Icon icon={TrashBin2} />
<span class="hidden md:inline">Delete Room</span>
</Button>
<Button class="btn btn-primary" onclick={startEdit}>
<Icon icon={Pen} />
Edit Room
</Button>
{:else if $membershipStatus === MembershipStatus.Initial}
<Button class="btn btn-neutral" disabled={loading} onclick={join}>
{#if loading}
<span class="loading loading-spinner loading-sm"></span>
{:else}
<Icon icon={Login3} />
{/if}
Join member list
</Button>
{:else if $membershipStatus === MembershipStatus.Pending}
<Button class="btn btn-neutral">
<Icon icon={ClockCircle} />
Membership pending
</Button>
{:else}
<Button class="btn btn-neutral" disabled={loading} onclick={leave}>
{#if loading}
<span class="loading loading-spinner loading-sm"></span>
{:else}
<Icon icon={Login3} />
{/if}
Leave member list
</Button>
{/if}
</div>
</ModalFooter> </ModalFooter>
</Modal> </Modal>
@@ -58,6 +58,7 @@
<Modal> <Modal>
<ModalBody> <ModalBody>
<div class="flex flex-col gap-2">
{#if event.pubkey === $pubkey} {#if event.pubkey === $pubkey}
<Button class="btn btn-neutral text-error" onclick={showDelete}> <Button class="btn btn-neutral text-error" onclick={showDelete}>
<Icon size={4} icon={TrashBin2} /> <Icon size={4} icon={TrashBin2} />
@@ -88,5 +89,6 @@
<Icon size={4} icon={SmileCircle} /> <Icon size={4} icon={SmileCircle} />
Send Reaction Send Reaction
</Button> </Button>
</div>
</ModalBody> </ModalBody>
</Modal> </Modal>
+17 -12
View File
@@ -12,6 +12,9 @@
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components/ModalBody.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
import Profile from "@app/components/Profile.svelte" import Profile from "@app/components/Profile.svelte"
import RoomName from "@app/components/RoomName.svelte" import RoomName from "@app/components/RoomName.svelte"
import RoomMembersAdd from "@app/components/RoomMembersAdd.svelte" import RoomMembersAdd from "@app/components/RoomMembersAdd.svelte"
@@ -63,18 +66,13 @@
<Modal> <Modal>
<ModalBody> <ModalBody>
<div class="flex min-w-0 flex-col gap-1"> <ModalHeader>
<h1 class="ellipsize whitespace-nowrap text-2xl font-bold">Members</h1> <ModalTitle>Members</ModalTitle>
<p class="ellipsize text-sm opacity-75">of <RoomName {url} {h} /></p> <ModalSubtitle>
</div> of <RoomName {url} {h} class="text-primary" />
{#if $userIsAdmin} </ModalSubtitle>
<div class="flex gap-2"> </ModalHeader>
<Button class="btn btn-primary" onclick={addMember}> <div class="flex flex-col gap-2">
<Icon icon={AddCircle} />
Add members
</Button>
</div>
{/if}
{#each $members as pubkey (pubkey)} {#each $members as pubkey (pubkey)}
<div class="card2 bg-alt relative"> <div class="card2 bg-alt relative">
<div class="flex items-center justify-between gap-2"> <div class="flex items-center justify-between gap-2">
@@ -103,11 +101,18 @@
</div> </div>
</div> </div>
{/each} {/each}
</div>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
{#if $userIsAdmin}
<Button class="btn btn-primary" onclick={addMember}>
<Icon icon={AddCircle} />
Add members
</Button>
{/if}
</ModalFooter> </ModalFooter>
</Modal> </Modal>
+1 -1
View File
@@ -114,7 +114,7 @@
<ModalBody> <ModalBody>
<ModalHeader> <ModalHeader>
<ModalTitle>Add Members</ModalTitle> <ModalTitle>Add Members</ModalTitle>
<ModalSubtitle>to <RoomName {url} {h} /></ModalSubtitle> <ModalSubtitle>to <RoomName {url} {h} class="text-primary" /></ModalSubtitle>
</ModalHeader> </ModalHeader>
<Field> <Field>
{#snippet label()} {#snippet label()}
+15 -11
View File
@@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import {displayRelayUrl, ManagementMethod} from "@welshman/util" import {ManagementMethod} from "@welshman/util"
import {manageRelay, displayProfileByPubkey} from "@welshman/app" import {manageRelay, displayProfileByPubkey} from "@welshman/app"
import MenuDots from "@assets/icons/menu-dots.svg?dataurl" import MenuDots from "@assets/icons/menu-dots.svg?dataurl"
import MinusCircle from "@assets/icons/minus-circle.svg?dataurl" import MinusCircle from "@assets/icons/minus-circle.svg?dataurl"
@@ -12,7 +12,11 @@
import Confirm from "@lib/components/Confirm.svelte" import Confirm from "@lib/components/Confirm.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import RelayName from "@app/components/RelayName.svelte"
import Profile from "@app/components/Profile.svelte" import Profile from "@app/components/Profile.svelte"
import SpaceMembersAdd from "@app/components/SpaceMembersAdd.svelte" import SpaceMembersAdd from "@app/components/SpaceMembersAdd.svelte"
import SpaceMembersBanned from "@app/components/SpaceMembersBanned.svelte" import SpaceMembersBanned from "@app/components/SpaceMembersBanned.svelte"
@@ -72,23 +76,18 @@
<Modal> <Modal>
<ModalBody> <ModalBody>
<div class="flex min-w-0 flex-col gap-1"> <ModalHeader>
<h1 class="ellipsize whitespace-nowrap text-2xl font-bold">Members</h1> <ModalTitle>Members</ModalTitle>
<p class="ellipsize text-sm opacity-75">of {displayRelayUrl(url)}</p> <ModalSubtitle>of <RelayName {url} class="text-primary" /></ModalSubtitle>
</div> </ModalHeader>
{#if $userIsAdmin} {#if $userIsAdmin}
<div class="flex gap-2">
<Button class="btn btn-primary" onclick={addMember}>
<Icon icon={AddCircle} />
Add members
</Button>
{#if $bans.length > 0} {#if $bans.length > 0}
<Button class="btn btn-neutral" onclick={showBannedPubkeyItems}> <Button class="btn btn-neutral" onclick={showBannedPubkeyItems}>
Banned users ({$bans.length}) Banned users ({$bans.length})
</Button> </Button>
{/if} {/if}
</div>
{/if} {/if}
<div class="flex flex-col gap-2">
{#each $members as pubkey (pubkey)} {#each $members as pubkey (pubkey)}
<div class="card2 card2-sm bg-alt relative"> <div class="card2 card2-sm bg-alt relative">
<div class="flex items-center justify-between gap-2"> <div class="flex items-center justify-between gap-2">
@@ -117,11 +116,16 @@
</div> </div>
</div> </div>
{/each} {/each}
</div>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
<Button class="btn btn-primary" onclick={addMember}>
<Icon icon={AddCircle} />
Add members
</Button>
</ModalFooter> </ModalFooter>
</Modal> </Modal>
@@ -59,6 +59,7 @@
<ModalTitle>Banned users</ModalTitle> <ModalTitle>Banned users</ModalTitle>
<ModalSubtitle>on {displayRelayUrl(url)}</ModalSubtitle> <ModalSubtitle>on {displayRelayUrl(url)}</ModalSubtitle>
</ModalHeader> </ModalHeader>
<div class="flex flex-col gap-2">
{#each $bans as { pubkey, reason } (pubkey)} {#each $bans as { pubkey, reason } (pubkey)}
<div class="card2 bg-alt relative"> <div class="card2 bg-alt relative">
<div class="flex items-center justify-between gap-2"> <div class="flex items-center justify-between gap-2">
@@ -87,6 +88,7 @@
</div> </div>
</div> </div>
{/each} {/each}
</div>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
+13 -5
View File
@@ -1,12 +1,16 @@
<script lang="ts"> <script lang="ts">
import {REPORT, displayRelayUrl} from "@welshman/util" import {REPORT} from "@welshman/util"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Modal from "@lib/components/Modal.svelte" import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte" import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalTitle from "@lib/components/ModalTitle.svelte"
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import ReportItem from "@app/components/ReportItem.svelte" import ReportItem from "@app/components/ReportItem.svelte"
import RelayName from "@app/components/RelayName.svelte"
import {deriveEventsForUrl} from "@app/core/state" import {deriveEventsForUrl} from "@app/core/state"
interface Props { interface Props {
@@ -22,13 +26,17 @@
<Modal> <Modal>
<ModalBody> <ModalBody>
<div class="flex min-w-0 flex-col gap-1"> <ModalHeader>
<h1 class="ellipsize whitespace-nowrap text-2xl font-bold">Reports</h1> <ModalTitle>Reports</ModalTitle>
<p class="ellipsize text-sm opacity-75">on {displayRelayUrl(url)}</p> <ModalSubtitle>on <RelayName {url} class="text-primary" /></ModalSubtitle>
</div> </ModalHeader>
<div class="flex flex-col gap-2">
{#each $reports as event (event.id)} {#each $reports as event (event.id)}
<ReportItem {url} {event} /> <ReportItem {url} {event} />
{:else}
<p class="py-12 text-center">No reports found.</p>
{/each} {/each}
</div>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
+1 -1
View File
@@ -10,6 +10,6 @@
const {children, ...props}: Props = $props() const {children, ...props}: Props = $props()
</script> </script>
<div class={cx("scroll-container overflow-y-auto min-h-0 flex flex-col gap-2 p-6", props.class)}> <div class={cx("scroll-container overflow-y-auto min-h-0 flex flex-col gap-4 p-6", props.class)}>
{@render children?.()} {@render children?.()}
</div> </div>
+1 -1
View File
@@ -9,7 +9,7 @@
</script> </script>
<div class="h-20 flex-shrink-0"></div> <div class="h-20 flex-shrink-0"></div>
<div class="flex absolute bottom-0 left-0 right-0 p-6 pt-2 rounded-b-box bg-base-100"> <div class="flex absolute bottom-0 left-0 right-0 p-6 py-4 rounded-b-box bg-base-200">
<div class="flex flex-grow gap-4 items-center justify-between"> <div class="flex flex-grow gap-4 items-center justify-between">
{@render children?.()} {@render children?.()}
</div> </div>