2026-06-18 10:52:04 +00:00
|
|
|
<script lang="ts">
|
|
|
|
|
import cx from "classnames"
|
|
|
|
|
import UsersGroup from "@assets/icons/users-group-rounded.svg?dataurl"
|
|
|
|
|
import Icon from "@lib/components/Icon.svelte"
|
|
|
|
|
import Badge from "@lib/components/Badge.svelte"
|
|
|
|
|
import Link from "@lib/components/Link.svelte"
|
|
|
|
|
import RelayIcon from "@app/components/RelayIcon.svelte"
|
|
|
|
|
import RelayName from "@app/components/RelayName.svelte"
|
2026-07-28 16:16:26 +00:00
|
|
|
import {userSpaceUrls} from "@app/rooms"
|
|
|
|
|
import {roomLists} from "@app/core"
|
2026-06-18 10:52:04 +00:00
|
|
|
import {makeSpacePath} from "@app/routes"
|
|
|
|
|
|
|
|
|
|
type Props = {
|
|
|
|
|
pubkey: string
|
|
|
|
|
isSelf?: boolean
|
|
|
|
|
class?: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const {pubkey, isSelf = false, ...props}: Props = $props()
|
|
|
|
|
|
2026-07-28 16:16:26 +00:00
|
|
|
const roomList = $roomLists.one(pubkey)
|
|
|
|
|
const spaceUrls = $derived($roomList?.urls() ?? [])
|
2026-06-18 10:52:04 +00:00
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<div class={cx("card card-sm flex flex-col gap-3 sm:gap-4", props.class)}>
|
|
|
|
|
<div class="flex items-center justify-between gap-2">
|
|
|
|
|
<div class="flex items-center gap-2">
|
|
|
|
|
<Icon icon={UsersGroup} size={5} />
|
|
|
|
|
<strong>Spaces</strong>
|
|
|
|
|
</div>
|
|
|
|
|
<Badge variant="neutral">{spaceUrls.length}</Badge>
|
|
|
|
|
</div>
|
|
|
|
|
{#if spaceUrls.length > 0}
|
|
|
|
|
<div class="flex flex-col gap-2 border-t border-line pt-4">
|
|
|
|
|
{#each spaceUrls as url (url)}
|
2026-07-28 16:16:26 +00:00
|
|
|
{@const count = $roomLists.pubkeysForUrl(url).get().length}
|
2026-06-18 10:52:04 +00:00
|
|
|
{@const isMember = !isSelf && $userSpaceUrls.includes(url)}
|
|
|
|
|
<Link
|
|
|
|
|
href={makeSpacePath(url)}
|
2026-06-29 22:48:43 +00:00
|
|
|
class="card card-interactive flex flex-row items-center justify-between gap-3 p-3 sm:p-4">
|
2026-06-18 10:52:04 +00:00
|
|
|
<RelayIcon {url} size={8} />
|
|
|
|
|
<div class="min-w-0 flex-1">
|
|
|
|
|
<div class="flex items-center gap-2">
|
|
|
|
|
<RelayName {url} class="truncate text-sm font-medium" />
|
|
|
|
|
{#if isMember}
|
|
|
|
|
<Badge variant="primary" class="text-xs">Member</Badge>
|
|
|
|
|
{/if}
|
|
|
|
|
</div>
|
|
|
|
|
<p class="text-xs opacity-75">
|
|
|
|
|
{#if count >= 1000}
|
|
|
|
|
{(count / 1000).toFixed(1).replace(/\.0$/, "")}K members
|
|
|
|
|
{:else}
|
|
|
|
|
{count} {count === 1 ? "member" : "members"}
|
|
|
|
|
{/if}
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</Link>
|
|
|
|
|
{/each}
|
|
|
|
|
</div>
|
|
|
|
|
{:else}
|
|
|
|
|
<p class="border-t border-line pt-4 text-sm opacity-75">
|
|
|
|
|
{isSelf ? "You aren't in any spaces yet." : "No spaces found."}
|
|
|
|
|
</p>
|
|
|
|
|
{/if}
|
|
|
|
|
</div>
|