forked from coracle/flotilla
Add relay members list and room join/leave events
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
import Spinner from "@lib/components/Spinner.svelte"
|
||||
import ModalHeader from "@lib/components/ModalHeader.svelte"
|
||||
import ModalFooter from "@lib/components/ModalFooter.svelte"
|
||||
import {alerts, getMembershipUrls, userMembership} from "@app/core/state"
|
||||
import {alerts, userSpaceUrls} from "@app/core/state"
|
||||
import {requestRelayClaim} from "@app/core/requests"
|
||||
import {createAlert} from "@app/core/commands"
|
||||
import {canSendPushNotifications} from "@app/util/push"
|
||||
@@ -174,7 +174,7 @@
|
||||
{#snippet input()}
|
||||
<select bind:value={url} class="select select-bordered">
|
||||
<option value="" disabled selected>Choose a space URL</option>
|
||||
{#each getMembershipUrls($userMembership) as url (url)}
|
||||
{#each $userSpaceUrls as url (url)}
|
||||
<option value={url}>{displayRelayUrl(url)}</option>
|
||||
{/each}
|
||||
</select>
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<script lang="ts">
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {getPubkeyTagValues} from "@welshman/util"
|
||||
import ProfileLink from "@app/components/ProfileLink.svelte"
|
||||
|
||||
type Props = {
|
||||
url: string
|
||||
event: TrustedEvent
|
||||
}
|
||||
|
||||
const {url, event}: Props = $props()
|
||||
</script>
|
||||
|
||||
{#each getPubkeyTagValues(event.tags) as pubkey}
|
||||
<div class="py-1 text-center text-xs opacity-75">
|
||||
<ProfileLink unstyled class="text-primary" {url} {pubkey} /> joined the room
|
||||
</div>
|
||||
{/each}
|
||||
@@ -0,0 +1,18 @@
|
||||
<script lang="ts">
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {getPubkeyTagValues} from "@welshman/util"
|
||||
import ProfileLink from "@app/components/ProfileLink.svelte"
|
||||
|
||||
type Props = {
|
||||
url: string
|
||||
event: TrustedEvent
|
||||
}
|
||||
|
||||
const {url, event}: Props = $props()
|
||||
</script>
|
||||
|
||||
{#each getPubkeyTagValues(event.tags) as pubkey}
|
||||
<div class="py-1 text-center text-xs opacity-75">
|
||||
<ProfileLink unstyled class="text-primary" {url} {pubkey} /> left the room
|
||||
</div>
|
||||
{/each}
|
||||
@@ -39,9 +39,7 @@
|
||||
import {
|
||||
ENABLE_ZAPS,
|
||||
MESSAGE_FILTER,
|
||||
userRoomsByUrl,
|
||||
hasMembershipUrl,
|
||||
memberships,
|
||||
deriveSpaceMembers,
|
||||
deriveEventsForUrl,
|
||||
deriveUserRooms,
|
||||
deriveOtherRooms,
|
||||
@@ -62,6 +60,7 @@
|
||||
const calendarPath = makeSpacePath(url, "calendar")
|
||||
const userRooms = deriveUserRooms(url)
|
||||
const otherRooms = deriveOtherRooms(url)
|
||||
const members = deriveSpaceMembers(url)
|
||||
const owner = $derived($relay?.profile?.pubkey)
|
||||
const hasAlerts = $derived($alerts.some(a => getTagValue("feed", a.tags)?.includes(url)))
|
||||
|
||||
@@ -83,7 +82,7 @@
|
||||
const showMembers = () =>
|
||||
pushModal(
|
||||
ProfileList,
|
||||
{url, pubkeys: members, title: `Members of`, subtitle: displayRelayUrl(url)},
|
||||
{url, pubkeys: $members, title: `Members of`, subtitle: displayRelayUrl(url)},
|
||||
{replaceState},
|
||||
)
|
||||
|
||||
@@ -108,10 +107,6 @@
|
||||
let replaceState = $state(false)
|
||||
let element: Element | undefined = $state()
|
||||
|
||||
const members = $derived(
|
||||
$memberships.filter(l => hasMembershipUrl(l, url)).map(l => l.event.pubkey),
|
||||
)
|
||||
|
||||
onMount(() => {
|
||||
replaceState = Boolean(element?.closest(".drawer"))
|
||||
})
|
||||
@@ -151,7 +146,7 @@
|
||||
<li>
|
||||
<Button onclick={showMembers}>
|
||||
<Icon icon={UserRounded} />
|
||||
View Members ({members.length})
|
||||
View Members ({$members.length})
|
||||
</Button>
|
||||
</li>
|
||||
{#if owner}
|
||||
@@ -163,7 +158,7 @@
|
||||
</li>
|
||||
{/if}
|
||||
<li>
|
||||
{#if $userRoomsByUrl.has(url)}
|
||||
{#if $userRooms.includes(url)}
|
||||
<Button onclick={leaveSpace} class="text-error">
|
||||
<Icon icon={Exit} />
|
||||
Leave Space
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
import Divider from "@lib/components/Divider.svelte"
|
||||
import CardButton from "@lib/components/CardButton.svelte"
|
||||
import MenuSpacesItem from "@app/components/MenuSpacesItem.svelte"
|
||||
import {userRoomsByUrl, PLATFORM_RELAYS} from "@app/core/state"
|
||||
import {userSpaceUrls, PLATFORM_RELAYS} from "@app/core/state"
|
||||
</script>
|
||||
|
||||
<div class="column menu gap-2">
|
||||
{#each PLATFORM_RELAYS as url (url)}
|
||||
<MenuSpacesItem {url} />
|
||||
{:else}
|
||||
{#if $userRoomsByUrl.size > 0}
|
||||
{#each $userRoomsByUrl.keys() as url (url)}
|
||||
{#if $userSpaceUrls.length > 0}
|
||||
{#each $userSpaceUrls as url (url)}
|
||||
<MenuSpacesItem {url} />
|
||||
{/each}
|
||||
<Divider />
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
import MenuOtherSpaces from "@app/components/MenuOtherSpaces.svelte"
|
||||
import MenuSettings from "@app/components/MenuSettings.svelte"
|
||||
import PrimaryNavItemSpace from "@app/components/PrimaryNavItemSpace.svelte"
|
||||
import {userRoomsByUrl, PLATFORM_RELAYS, PLATFORM_LOGO} from "@app/core/state"
|
||||
import {userSpaceUrls, PLATFORM_RELAYS, PLATFORM_LOGO} from "@app/core/state"
|
||||
import {pushModal} from "@app/util/modal"
|
||||
import {makeSpacePath} from "@app/util/routes"
|
||||
import {notifications} from "@app/util/notifications"
|
||||
@@ -31,7 +31,8 @@
|
||||
|
||||
const {children}: Props = $props()
|
||||
|
||||
const showSpacesMenu = () => (spaceUrls.length > 0 ? pushModal(MenuSpaces) : pushModal(SpaceAdd))
|
||||
const showSpacesMenu = () =>
|
||||
$userSpaceUrls.length > 0 ? pushModal(MenuSpaces) : pushModal(SpaceAdd)
|
||||
|
||||
const showOtherSpacesMenu = () => pushModal(MenuOtherSpaces, {urls: secondarySpaceUrls})
|
||||
|
||||
@@ -50,9 +51,8 @@
|
||||
const itemHeight = 56
|
||||
const navPadding = 6 * itemHeight
|
||||
const itemLimit = $derived((windowHeight - navPadding) / itemHeight)
|
||||
const spaceUrls = $derived(Array.from($userRoomsByUrl.keys()))
|
||||
const [primarySpaceUrls, secondarySpaceUrls] = $derived(splitAt(itemLimit, spaceUrls))
|
||||
const anySpaceNotifications = $derived(spaceUrls.some(hasNotification))
|
||||
const [primarySpaceUrls, secondarySpaceUrls] = $derived(splitAt(itemLimit, $userSpaceUrls))
|
||||
const anySpaceNotifications = $derived($userSpaceUrls.some(hasNotification))
|
||||
const otherSpaceNotifications = $derived(secondarySpaceUrls.some(hasNotification))
|
||||
</script>
|
||||
|
||||
|
||||
@@ -5,11 +5,15 @@
|
||||
import type {Filter} from "@welshman/util"
|
||||
import {deriveEvents} from "@welshman/store"
|
||||
import {formatTimestampRelative} from "@welshman/lib"
|
||||
import {NOTE, ROOMS, COMMENT, getRelayTags, getListTags} from "@welshman/util"
|
||||
import {NOTE, ROOMS, COMMENT} from "@welshman/util"
|
||||
import {repository, loadRelaySelections} from "@welshman/app"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import ProfileSpaces from "@app/components/ProfileSpaces.svelte"
|
||||
import {membershipsByPubkey, MESSAGE_KINDS} from "@app/core/state"
|
||||
import {
|
||||
deriveGroupSelections,
|
||||
getSpaceUrlsFromGroupSelections,
|
||||
MESSAGE_KINDS,
|
||||
} from "@app/core/state"
|
||||
import {goToEvent} from "@app/util/routes"
|
||||
import {pushModal} from "@app/util/modal"
|
||||
|
||||
@@ -21,8 +25,8 @@
|
||||
const {pubkey, url}: Props = $props()
|
||||
const filters: Filter[] = [{authors: [pubkey], limit: 1}]
|
||||
const events = deriveEvents(repository, {filters})
|
||||
const membership = $derived($membershipsByPubkey.get(pubkey))
|
||||
const relays = $derived(getRelayTags(getListTags(membership)))
|
||||
const selections = deriveGroupSelections(pubkey)
|
||||
const spaceUrls = $derived(getSpaceUrlsFromGroupSelections($selections))
|
||||
|
||||
const viewEvent = () => goToEvent($events[0]!)
|
||||
|
||||
@@ -49,10 +53,10 @@
|
||||
Last active {formatTimestampRelative($events[0].created_at)}
|
||||
</Button>
|
||||
{/if}
|
||||
{#if relays.length > 0}
|
||||
{#if spaceUrls.length > 0}
|
||||
<Button onclick={openSpaces} class="badge badge-neutral">
|
||||
{relays.length}
|
||||
{relays.length === 1 ? "space" : "spaces"}
|
||||
{spaceUrls.length}
|
||||
{spaceUrls.length === 1 ? "space" : "spaces"}
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -19,13 +19,7 @@
|
||||
import ModalFooter from "@lib/components/ModalFooter.svelte"
|
||||
import {pushToast} from "@app/util/toast"
|
||||
import {logout} from "@app/core/commands"
|
||||
import {
|
||||
INDEXER_RELAYS,
|
||||
PLATFORM_NAME,
|
||||
userMembership,
|
||||
getMembershipUrls,
|
||||
userWriteRelays,
|
||||
} from "@app/core/state"
|
||||
import {INDEXER_RELAYS, PLATFORM_NAME, userSpaceUrls, userWriteRelays} from "@app/core/state"
|
||||
|
||||
let progress: number | undefined = $state(undefined)
|
||||
let confirmText = $state("")
|
||||
@@ -46,11 +40,7 @@
|
||||
const profileEvent = makeEvent(PROFILE, createProfile({name: "[deleted]"}))
|
||||
const vanishEvent = makeEvent(62, {tags: [["relay", "ALL_RELAYS"]]})
|
||||
const denominator = chunks.length + 2
|
||||
const relays = uniq([
|
||||
...INDEXER_RELAYS,
|
||||
...$userWriteRelays,
|
||||
...getMembershipUrls($userMembership),
|
||||
])
|
||||
const relays = uniq([...INDEXER_RELAYS, ...$userWriteRelays, ...$userSpaceUrls])
|
||||
|
||||
let step = 0
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
import SpaceAvatar from "@app/components/SpaceAvatar.svelte"
|
||||
import RelayName from "@app/components/RelayName.svelte"
|
||||
import {makeSpacePath} from "@app/util/routes"
|
||||
import {getMembershipUrls, membershipsByPubkey} from "@app/core/state"
|
||||
import {deriveGroupSelections, getSpaceUrlsFromGroupSelections} from "@app/core/state"
|
||||
|
||||
type Props = {
|
||||
pubkey: string
|
||||
@@ -16,7 +16,8 @@
|
||||
|
||||
const {pubkey}: Props = $props()
|
||||
|
||||
const spaceUrls = $derived(getMembershipUrls($membershipsByPubkey.get(pubkey)))
|
||||
const selections = deriveGroupSelections(pubkey)
|
||||
const spaceUrls = $derived(getSpaceUrlsFromGroupSelections($selections))
|
||||
|
||||
const back = () => history.back()
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script lang="ts">
|
||||
import {gt} from "@welshman/lib"
|
||||
import {deriveRelay} from "@welshman/app"
|
||||
import Ghost from "@assets/icons/ghost-smile.svg?dataurl"
|
||||
import CheckCircle from "@assets/icons/check-circle.svg?dataurl"
|
||||
@@ -7,7 +6,7 @@
|
||||
import RelayName from "@app/components/RelayName.svelte"
|
||||
import RelayDescription from "@app/components/RelayDescription.svelte"
|
||||
import ProfileCircles from "@app/components/ProfileCircles.svelte"
|
||||
import {membersByUrl, userRoomsByUrl} from "@app/core/state"
|
||||
import {deriveSpaceMembers, deriveUserRooms} from "@app/core/state"
|
||||
|
||||
type Props = {
|
||||
url: string
|
||||
@@ -15,6 +14,8 @@
|
||||
|
||||
const {url}: Props = $props()
|
||||
const relay = deriveRelay(url)
|
||||
const rooms = deriveUserRooms(url)
|
||||
const members = deriveSpaceMembers(url)
|
||||
</script>
|
||||
|
||||
<div class="col-4 text-left">
|
||||
@@ -31,7 +32,7 @@
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{#if $userRoomsByUrl.has(url)}
|
||||
{#if $rooms.includes(url)}
|
||||
<div
|
||||
class="tooltip absolute -right-1 -top-1 h-5 w-5 rounded-full bg-primary"
|
||||
data-tip="You are already a member of this space.">
|
||||
@@ -48,10 +49,10 @@
|
||||
</div>
|
||||
<RelayDescription {url} />
|
||||
</div>
|
||||
{#if gt($membersByUrl.get(url)?.size, 0)}
|
||||
{#if $members.length > 0}
|
||||
<div class="row-2 card2 card2-sm bg-alt">
|
||||
Members:
|
||||
<ProfileCircles pubkeys={Array.from($membersByUrl.get(url) || [])} />
|
||||
<ProfileCircles pubkeys={$members} />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import {onMount} from "svelte"
|
||||
import {sleep, nthEq} from "@welshman/lib"
|
||||
import {request} from "@welshman/net"
|
||||
import {displayRelayUrl, AUTH_INVITE} from "@welshman/util"
|
||||
import {displayRelayUrl, RELAY_INVITE} from "@welshman/util"
|
||||
import LinkRound from "@assets/icons/link-round.svg?dataurl"
|
||||
import Copy from "@assets/icons/copy.svg?dataurl"
|
||||
import Spinner from "@lib/components/Spinner.svelte"
|
||||
@@ -38,7 +38,7 @@
|
||||
request({
|
||||
relays: [url],
|
||||
autoClose: true,
|
||||
filters: [{kinds: [AUTH_INVITE]}],
|
||||
filters: [{kinds: [RELAY_INVITE]}],
|
||||
}),
|
||||
sleep(2000),
|
||||
])
|
||||
@@ -83,7 +83,7 @@
|
||||
This invite link can be used by clicking "Add Space" and pasting it there.
|
||||
{#if !claim}
|
||||
This space did not issue a claim for this link, so additional steps might be
|
||||
required for people using this invite link.
|
||||
required.
|
||||
{/if}
|
||||
</p>
|
||||
{/snippet}
|
||||
|
||||
Reference in New Issue
Block a user