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 {
+7 -5
View File
@@ -19,11 +19,13 @@
<ModalHeader> <ModalHeader>
<ModalTitle>People in this conversation</ModalTitle> <ModalTitle>People in this conversation</ModalTitle>
</ModalHeader> </ModalHeader>
{#each pubkeys as pubkey (pubkey)} <div class="flex flex-col gap-2">
<div class="card2 bg-alt"> {#each pubkeys as pubkey (pubkey)}
<Profile {pubkey} /> <div class="card2 bg-alt">
</div> <Profile {pubkey} />
{/each} </div>
{/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>
+19 -17
View File
@@ -27,24 +27,26 @@
<Modal> <Modal>
<ModalBody> <ModalBody>
<Button class="btn btn-primary" onclick={startChat}> <div class="flex flex-col gap-2">
<Icon size={5} icon={ChatSquare} /> <Button class="btn btn-primary" onclick={startChat}>
Start chat <Icon size={5} icon={ChatSquare} />
</Button> Start chat
<Button class="btn btn-neutral" onclick={markAsRead}>
<Icon size={5} icon={Check} />
Mark all read
</Button>
{#if $notificationSettings.messages}
<Button class="btn btn-neutral" onclick={disableAlerts}>
<Icon size={4} icon={BellOff} />
Disable alerts
</Button> </Button>
{:else} <Button class="btn btn-neutral" onclick={markAsRead}>
<Button class="btn btn-neutral" onclick={enableAlerts}> <Icon size={5} icon={Check} />
<Icon size={4} icon={Bell} /> Mark all read
Enable alerts
</Button> </Button>
{/if} {#if $notificationSettings.messages}
<Button class="btn btn-neutral" onclick={disableAlerts}>
<Icon size={4} icon={BellOff} />
Disable alerts
</Button>
{:else}
<Button class="btn btn-neutral" onclick={enableAlerts}>
<Icon size={4} icon={Bell} />
Enable alerts
</Button>
{/if}
</div>
</ModalBody> </ModalBody>
</Modal> </Modal>
+18 -16
View File
@@ -49,21 +49,23 @@
<Modal> <Modal>
<ModalBody> <ModalBody>
<Button class="btn btn-neutral" onclick={showInfo}> <div class="flex flex-col gap-2">
<Icon size={4} icon={Code2} /> <Button class="btn btn-neutral" onclick={showInfo}>
Message Info <Icon size={4} icon={Code2} />
</Button> Message Info
<Button class="btn btn-neutral w-full" onclick={copyText}> </Button>
<Icon size={4} icon={Copy} /> <Button class="btn btn-neutral w-full" onclick={copyText}>
Copy Text <Icon size={4} icon={Copy} />
</Button> Copy Text
<Button class="btn btn-neutral w-full" onclick={sendReply}> </Button>
<Icon size={4} icon={Reply} /> <Button class="btn btn-neutral w-full" onclick={sendReply}>
Send Reply <Icon size={4} icon={Reply} />
</Button> Send Reply
<Button class="btn btn-primary w-full" onclick={showEmojiPicker}> </Button>
<Icon size={4} icon={SmileCircle} /> <Button class="btn btn-primary w-full" onclick={showEmojiPicker}>
Send Reaction <Icon size={4} icon={SmileCircle} />
</Button> Send Reaction
</Button>
</div>
</ModalBody> </ModalBody>
</Modal> </Modal>
+96 -94
View File
@@ -25,99 +25,101 @@
<Modal> <Modal>
<ModalBody> <ModalBody>
<Link replaceState href="/settings/profile"> <div class="flex flex-col gap-2">
<CardButton class="btn-neutral"> <Link replaceState href="/settings/profile">
{#snippet icon()} <CardButton class="btn-neutral">
<div><Icon icon={UserRounded} size={7} /></div> {#snippet icon()}
{/snippet} <div><Icon icon={UserRounded} size={7} /></div>
{#snippet title()} {/snippet}
<div>Profile</div> {#snippet title()}
{/snippet} <div>Profile</div>
{#snippet info()} {/snippet}
<div>Customize your user profile</div> {#snippet info()}
{/snippet} <div>Customize your user profile</div>
</CardButton> {/snippet}
</Link> </CardButton>
<Link replaceState href="/settings/alerts"> </Link>
<CardButton class="btn-neutral"> <Link replaceState href="/settings/alerts">
{#snippet icon()} <CardButton class="btn-neutral">
<div><Icon icon={Bell} size={7} /></div> {#snippet icon()}
{/snippet} <div><Icon icon={Bell} size={7} /></div>
{#snippet title()} {/snippet}
<div>Alerts</div> {#snippet title()}
{/snippet} <div>Alerts</div>
{#snippet info()} {/snippet}
<div>Set up email digests and push notifications</div> {#snippet info()}
{/snippet} <div>Set up email digests and push notifications</div>
</CardButton> {/snippet}
</Link> </CardButton>
<Link replaceState href="/settings/wallet"> </Link>
<CardButton class="btn-neutral"> <Link replaceState href="/settings/wallet">
{#snippet icon()} <CardButton class="btn-neutral">
<div><Icon icon={Wallet} size={7} /></div> {#snippet icon()}
{/snippet} <div><Icon icon={Wallet} size={7} /></div>
{#snippet title()} {/snippet}
<div>Wallet</div> {#snippet title()}
{/snippet} <div>Wallet</div>
{#snippet info()} {/snippet}
<div>Connect a bitcoin wallet for sending social tips</div> {#snippet info()}
{/snippet} <div>Connect a bitcoin wallet for sending social tips</div>
</CardButton> {/snippet}
</Link> </CardButton>
<Link replaceState href="/settings/relays"> </Link>
<CardButton class="btn-neutral"> <Link replaceState href="/settings/relays">
{#snippet icon()} <CardButton class="btn-neutral">
<div><Icon icon={Server} size={7} /></div> {#snippet icon()}
{/snippet} <div><Icon icon={Server} size={7} /></div>
{#snippet title()} {/snippet}
<div>Relays</div> {#snippet title()}
{/snippet} <div>Relays</div>
{#snippet info()} {/snippet}
<div>Control how {PLATFORM_NAME} talks to the network</div> {#snippet info()}
{/snippet} <div>Control how {PLATFORM_NAME} talks to the network</div>
</CardButton> {/snippet}
</Link> </CardButton>
<Link replaceState href="/settings/content"> </Link>
<CardButton class="btn-neutral"> <Link replaceState href="/settings/content">
{#snippet icon()} <CardButton class="btn-neutral">
<div><Icon icon={Settings} size={7} /></div> {#snippet icon()}
{/snippet} <div><Icon icon={Settings} size={7} /></div>
{#snippet title()} {/snippet}
<div>Settings</div> {#snippet title()}
{/snippet} <div>Settings</div>
{#snippet info()} {/snippet}
<div>Get into the details about how {PLATFORM_NAME} works</div> {#snippet info()}
{/snippet} <div>Get into the details about how {PLATFORM_NAME} works</div>
</CardButton> {/snippet}
</Link> </CardButton>
<Button onclick={toggleTheme}> </Link>
<CardButton class="btn-neutral"> <Button onclick={toggleTheme}>
{#snippet icon()} <CardButton class="btn-neutral">
<div><Icon icon={Moon} size={7} /></div> {#snippet icon()}
{/snippet} <div><Icon icon={Moon} size={7} /></div>
{#snippet title()} {/snippet}
<div>Theme</div> {#snippet title()}
{/snippet} <div>Theme</div>
{#snippet info()} {/snippet}
<div>Switch between light and dark mode</div> {#snippet info()}
{/snippet} <div>Switch between light and dark mode</div>
</CardButton> {/snippet}
</Button> </CardButton>
<Link replaceState href="/settings/about"> </Button>
<CardButton class="btn-neutral"> <Link replaceState href="/settings/about">
{#snippet icon()} <CardButton class="btn-neutral">
<div><Icon icon={Code2} size={7} /></div> {#snippet icon()}
{/snippet} <div><Icon icon={Code2} size={7} /></div>
{#snippet title()} {/snippet}
<div>About</div> {#snippet title()}
{/snippet} <div>About</div>
{#snippet info()} {/snippet}
<div>Learn about {PLATFORM_NAME} and support the developer</div> {#snippet info()}
{/snippet} <div>Learn about {PLATFORM_NAME} and support the developer</div>
</CardButton> {/snippet}
</Link> </CardButton>
<Button onclick={logout} class="btn btn-neutral"> </Link>
<Icon icon={Exit} /> Log Out <Button onclick={logout} class="btn btn-neutral">
</Button> <Icon icon={Exit} /> Log Out
</Button>
</div>
</ModalBody> </ModalBody>
</Modal> </Modal>
+5 -2
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>
{$display} <span class={props.class}>
{$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>
+31 -29
View File
@@ -58,35 +58,37 @@
<Modal> <Modal>
<ModalBody> <ModalBody>
{#if event.pubkey === $pubkey} <div class="flex flex-col gap-2">
<Button class="btn btn-neutral text-error" onclick={showDelete}> {#if event.pubkey === $pubkey}
<Icon size={4} icon={TrashBin2} /> <Button class="btn btn-neutral text-error" onclick={showDelete}>
Delete Message <Icon size={4} icon={TrashBin2} />
Delete Message
</Button>
{/if}
<Button class="btn btn-neutral" onclick={showInfo}>
<Icon size={4} icon={Code2} />
Message Info
</Button> </Button>
{/if} {#if path}
<Button class="btn btn-neutral" onclick={showInfo}> <Link class="btn btn-neutral" href={path}>
<Icon size={4} icon={Code2} /> <Icon size={4} icon={MenuDots} />
Message Info View Details
</Button> </Link>
{#if path} {/if}
<Link class="btn btn-neutral" href={path}> {#if ENABLE_ZAPS}
<Icon size={4} icon={MenuDots} /> <ZapButton replaceState {url} {event} class="btn btn-neutral w-full">
View Details <Icon size={4} icon={Bolt} />
</Link> Send Zap
{/if} </ZapButton>
{#if ENABLE_ZAPS} {/if}
<ZapButton replaceState {url} {event} class="btn btn-neutral w-full"> <Button class="btn btn-neutral w-full" onclick={sendReply}>
<Icon size={4} icon={Bolt} /> <Icon size={4} icon={Reply} />
Send Zap Send Reply
</ZapButton> </Button>
{/if} <Button class="btn btn-neutral w-full" onclick={showEmojiPicker}>
<Button class="btn btn-neutral w-full" onclick={sendReply}> <Icon size={4} icon={SmileCircle} />
<Icon size={4} icon={Reply} /> Send Reaction
Send Reply </Button>
</Button> </div>
<Button class="btn btn-neutral w-full" onclick={showEmojiPicker}>
<Icon size={4} icon={SmileCircle} />
Send Reaction
</Button>
</ModalBody> </ModalBody>
</Modal> </Modal>
+43 -38
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,51 +66,53 @@
<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} /> {#each $members as pubkey (pubkey)}
Add members <div class="card2 bg-alt relative">
</Button> <div class="flex items-center justify-between gap-2">
</div> <div class="min-w-0 flex-1">
{/if} <Profile {pubkey} {url} />
{#each $members as pubkey (pubkey)} </div>
<div class="card2 bg-alt relative"> <div class="relative">
<div class="flex items-center justify-between gap-2"> <Button class="btn btn-circle btn-ghost btn-sm" onclick={() => toggleMenu(pubkey)}>
<div class="min-w-0 flex-1"> <Icon icon={MenuDots} />
<Profile {pubkey} {url} /> </Button>
</div> {#if menuPubkey === pubkey}
<div class="relative"> <Popover hideOnClick onClose={closeMenu}>
<Button class="btn btn-circle btn-ghost btn-sm" onclick={() => toggleMenu(pubkey)}> <ul
<Icon icon={MenuDots} /> transition:fly
</Button> class="menu absolute right-0 z-popover mt-2 w-48 gap-1 rounded-box bg-base-100 p-2 shadow-md">
{#if menuPubkey === pubkey} <li>
<Popover hideOnClick onClose={closeMenu}> <Button class="text-error" onclick={() => removeMember(pubkey)}>
<ul <Icon icon={MinusCircle} />
transition:fly Remove Member
class="menu absolute right-0 z-popover mt-2 w-48 gap-1 rounded-box bg-base-100 p-2 shadow-md"> </Button>
<li> </li>
<Button class="text-error" onclick={() => removeMember(pubkey)}> </ul>
<Icon icon={MinusCircle} /> </Popover>
Remove Member {/if}
</Button> </div>
</li>
</ul>
</Popover>
{/if}
</div> </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()}
+45 -41
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,56 +76,56 @@
<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"> {#if $bans.length > 0}
<Button class="btn btn-primary" onclick={addMember}> <Button class="btn btn-neutral" onclick={showBannedPubkeyItems}>
<Icon icon={AddCircle} /> Banned users ({$bans.length})
Add members
</Button> </Button>
{#if $bans.length > 0} {/if}
<Button class="btn btn-neutral" onclick={showBannedPubkeyItems}>
Banned users ({$bans.length})
</Button>
{/if}
</div>
{/if} {/if}
{#each $members as pubkey (pubkey)} <div class="flex flex-col gap-2">
<div class="card2 card2-sm bg-alt relative"> {#each $members as pubkey (pubkey)}
<div class="flex items-center justify-between gap-2"> <div class="card2 card2-sm bg-alt relative">
<div class="min-w-0 flex-1"> <div class="flex items-center justify-between gap-2">
<Profile {pubkey} {url} /> <div class="min-w-0 flex-1">
</div> <Profile {pubkey} {url} />
<div class="relative"> </div>
<Button class="btn btn-circle btn-ghost btn-sm" onclick={() => toggleMenu(pubkey)}> <div class="relative">
<Icon icon={MenuDots} /> <Button class="btn btn-circle btn-ghost btn-sm" onclick={() => toggleMenu(pubkey)}>
</Button> <Icon icon={MenuDots} />
{#if menuPubkey === pubkey} </Button>
<Popover hideOnClick onClose={closeMenu}> {#if menuPubkey === pubkey}
<ul <Popover hideOnClick onClose={closeMenu}>
transition:fly <ul
class="menu absolute right-0 z-popover mt-2 w-48 gap-1 rounded-box bg-base-100 p-2 shadow-md"> transition:fly
<li> class="menu absolute right-0 z-popover mt-2 w-48 gap-1 rounded-box bg-base-100 p-2 shadow-md">
<Button class="text-error" onclick={() => banMember(pubkey)}> <li>
<Icon icon={MinusCircle} /> <Button class="text-error" onclick={() => banMember(pubkey)}>
Ban User <Icon icon={MinusCircle} />
</Button> Ban User
</li> </Button>
</ul> </li>
</Popover> </ul>
{/if} </Popover>
{/if}
</div>
</div> </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>
+28 -26
View File
@@ -59,34 +59,36 @@
<ModalTitle>Banned users</ModalTitle> <ModalTitle>Banned users</ModalTitle>
<ModalSubtitle>on {displayRelayUrl(url)}</ModalSubtitle> <ModalSubtitle>on {displayRelayUrl(url)}</ModalSubtitle>
</ModalHeader> </ModalHeader>
{#each $bans as { pubkey, reason } (pubkey)} <div class="flex flex-col gap-2">
<div class="card2 bg-alt relative"> {#each $bans as { pubkey, reason } (pubkey)}
<div class="flex items-center justify-between gap-2"> <div class="card2 bg-alt relative">
<div class="min-w-0 flex-1"> <div class="flex items-center justify-between gap-2">
<Profile {pubkey} {url} /> <div class="min-w-0 flex-1">
</div> <Profile {pubkey} {url} />
<div class="relative"> </div>
<Button class="btn btn-circle btn-ghost btn-sm" onclick={() => toggleMenu(pubkey)}> <div class="relative">
<Icon icon={MenuDots} /> <Button class="btn btn-circle btn-ghost btn-sm" onclick={() => toggleMenu(pubkey)}>
</Button> <Icon icon={MenuDots} />
{#if menuPubkey === pubkey} </Button>
<Popover hideOnClick onClose={closeMenu}> {#if menuPubkey === pubkey}
<ul <Popover hideOnClick onClose={closeMenu}>
transition:fly <ul
class="menu absolute right-0 z-popover mt-2 w-48 gap-1 rounded-box bg-base-100 p-2 shadow-md"> transition:fly
<li> class="menu absolute right-0 z-popover mt-2 w-48 gap-1 rounded-box bg-base-100 p-2 shadow-md">
<Button onclick={() => restoreMember(pubkey)}> <li>
<Icon icon={Restart} /> <Button onclick={() => restoreMember(pubkey)}>
Restore User <Icon icon={Restart} />
</Button> Restore User
</li> </Button>
</ul> </li>
</Popover> </ul>
{/if} </Popover>
{/if}
</div>
</div> </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}>
+15 -7
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>
</ModalHeader>
<div class="flex flex-col gap-2">
{#each $reports as event (event.id)}
<ReportItem {url} {event} />
{:else}
<p class="py-12 text-center">No reports found.</p>
{/each}
</div> </div>
{#each $reports as event (event.id)}
<ReportItem {url} {event} />
{/each}
</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>