Detect nip29 support for create room button

This commit is contained in:
Jon Staab 2025-05-27 16:22:20 -07:00
parent 4ba6c72459
commit e57b5721f6
5 changed files with 67 additions and 40 deletions

View file

@ -1,6 +1,7 @@
<script lang="ts"> <script lang="ts">
import {onMount} from "svelte" import {onMount} from "svelte"
import {displayRelayUrl} from "@welshman/util" import {displayRelayUrl} from "@welshman/util"
import {deriveRelay} from "@welshman/app"
import {fly} from "@lib/transition" 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"
@ -20,6 +21,7 @@
memberships, memberships,
deriveUserRooms, deriveUserRooms,
deriveOtherRooms, deriveOtherRooms,
hasNip29,
} from "@app/state" } from "@app/state"
import {notifications} from "@app/notifications" import {notifications} from "@app/notifications"
import {pushModal} from "@app/modal" import {pushModal} from "@app/modal"
@ -27,6 +29,7 @@
const {url} = $props() const {url} = $props()
const relay = deriveRelay(url)
const threadsPath = makeSpacePath(url, "threads") const threadsPath = makeSpacePath(url, "threads")
const calendarPath = makeSpacePath(url, "calendar") const calendarPath = makeSpacePath(url, "calendar")
const userRooms = deriveUserRooms(url) const userRooms = deriveUserRooms(url)
@ -143,10 +146,12 @@
{#each $otherRooms as room, i (room)} {#each $otherRooms as room, i (room)}
<MenuSpaceRoomItem {replaceState} {url} {room} /> <MenuSpaceRoomItem {replaceState} {url} {room} />
{/each} {/each}
{#if hasNip29($relay)}
<SecondaryNavItem {replaceState} onclick={addRoom}> <SecondaryNavItem {replaceState} onclick={addRoom}>
<Icon icon="add-circle" /> <Icon icon="add-circle" />
Create room Create room
</SecondaryNavItem> </SecondaryNavItem>
{/if}
</div> </div>
</SecondaryNavSection> </SecondaryNavSection>
</div> </div>

View file

@ -23,7 +23,6 @@
const back = () => history.back() const back = () => history.back()
const tryCreate = async () => { const tryCreate = async () => {
if (hasNip29($relay)) {
const createMessage = await getThunkError(nip29.createRoom(url, room)) const createMessage = await getThunkError(nip29.createRoom(url, room))
if (createMessage && !createMessage.match(/^duplicate:|already a member/)) { if (createMessage && !createMessage.match(/^duplicate:|already a member/)) {
@ -41,7 +40,6 @@
if (joinMessage && !joinMessage.includes("already")) { if (joinMessage && !joinMessage.includes("already")) {
return pushToast({theme: "error", message: joinMessage}) return pushToast({theme: "error", message: joinMessage})
} }
}
addRoomMembership(url, room, name) addRoomMembership(url, room, name)
goto(makeSpacePath(url, room)) goto(makeSpacePath(url, room))
@ -72,6 +70,7 @@
</div> </div>
{/snippet} {/snippet}
</ModalHeader> </ModalHeader>
{#if hasNip29($relay)}
<Field> <Field>
{#snippet label()} {#snippet label()}
<p>Room Name</p> <p>Room Name</p>
@ -83,12 +82,18 @@
</label> </label>
{/snippet} {/snippet}
</Field> </Field>
{:else}
<p class="bg-alt card2 row-2">
<Icon icon="danger" />
This relay does not support creating rooms.
</p>
{/if}
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon="alt-arrow-left" /> <Icon icon="alt-arrow-left" />
Go back Go back
</Button> </Button>
<Button type="submit" class="btn btn-primary" disabled={!name || loading}> <Button type="submit" class="btn btn-primary" disabled={!name || loading || !hasNip29($relay)}>
<Spinner {loading}>Create Room</Spinner> <Spinner {loading}>Create Room</Spinner>
<Icon icon="alt-arrow-right" /> <Icon icon="alt-arrow-right" />
</Button> </Button>

View file

@ -3,6 +3,7 @@ import {get, derived} from "svelte/store"
import * as nip19 from "nostr-tools/nip19" import * as nip19 from "nostr-tools/nip19"
import { import {
remove, remove,
uniqBy,
sortBy, sortBy,
sort, sort,
uniq, uniq,
@ -528,7 +529,7 @@ export const channels = derived(
} }
} }
return $channels return uniqBy(c => c.id, $channels)
}, },
) )
@ -594,13 +595,19 @@ export const userMembership = withGetter(
) )
export const userRoomsByUrl = withGetter( export const userRoomsByUrl = withGetter(
derived(userMembership, $userMembership => { derived([userMembership, channelsById], ([$userMembership, $channelsById]) => {
const tags = getListTags($userMembership) const tags = getListTags($userMembership)
const $userRoomsByUrl = new Map<string, Set<string>>() const $userRoomsByUrl = new Map<string, Set<string>>()
for (const url of getRelayTagValues(tags)) {
$userRoomsByUrl.set(normalizeRelayUrl(url), new Set())
}
for (const [_, room, url] of getGroupTags(tags)) { for (const [_, room, url] of getGroupTags(tags)) {
if ($channelsById.has(makeChannelId(url, room))) {
addToMapKey($userRoomsByUrl, normalizeRelayUrl(url), room) addToMapKey($userRoomsByUrl, normalizeRelayUrl(url), room)
} }
}
return $userRoomsByUrl return $userRoomsByUrl
}), }),

View file

@ -1,6 +1,9 @@
<script lang="ts"> <script lang="ts">
import {onMount} from "svelte" import {onMount} from "svelte"
import {addToMapKey, dec, gt} from "@welshman/lib" import {addToMapKey, dec, gt} from "@welshman/lib"
import {GROUPS} from "@welshman/util"
import {Router} from "@welshman/router"
import {load} from "@welshman/net"
import type {Relay} from "@welshman/app" import type {Relay} from "@welshman/app"
import {relays, createSearch, loadRelay, loadRelaySelections} from "@welshman/app" import {relays, createSearch, loadRelay, loadRelaySelections} from "@welshman/app"
import {createScroller} from "@lib/html" import {createScroller} from "@lib/html"
@ -24,8 +27,12 @@
import {pushModal} from "@app/modal" import {pushModal} from "@app/modal"
const discoverRelays = () => const discoverRelays = () =>
Promise.all( Promise.all([
getDefaultPubkeys().map(async pubkey => { load({
filters: [{kinds: [GROUPS]}],
relays: Router.get().Index().getUrls(),
}),
...getDefaultPubkeys().map(async pubkey => {
await loadRelaySelections(pubkey) await loadRelaySelections(pubkey)
const membership = await loadMembership(pubkey) const membership = await loadMembership(pubkey)
@ -33,7 +40,7 @@
await Promise.all(urls.map(url => loadRelay(url))) await Promise.all(urls.map(url => loadRelay(url)))
}), }),
) ])
const wotGraph = $derived.by(() => { const wotGraph = $derived.by(() => {
const scores = new Map<string, Set<string>>() const scores = new Map<string, Set<string>>()
@ -87,7 +94,7 @@
}) })
</script> </script>
<Page> <Page class="cw-full">
<div class="content column gap-4" bind:this={element}> <div class="content column gap-4" bind:this={element}>
<PageHeader> <PageHeader>
{#snippet title()} {#snippet title()}

View file

@ -18,6 +18,7 @@
import RoomCreate from "@app/components/RoomCreate.svelte" import RoomCreate from "@app/components/RoomCreate.svelte"
import RelayDescription from "@app/components/RelayDescription.svelte" import RelayDescription from "@app/components/RelayDescription.svelte"
import { import {
hasNip29,
decodeRelay, decodeRelay,
channelIsLocked, channelIsLocked,
makeChannelId, makeChannelId,
@ -183,10 +184,12 @@
</div> </div>
</Link> </Link>
{/each} {/each}
{#if hasNip29($relay)}
<Button onclick={addRoom} class="btn btn-neutral whitespace-nowrap"> <Button onclick={addRoom} class="btn btn-neutral whitespace-nowrap">
<Icon icon="add-circle" /> <Icon icon="add-circle" />
Create Create
</Button> </Button>
{/if}
</div> </div>
{#if pubkey} {#if pubkey}
<Divider>Recent posts from the relay admin</Divider> <Divider>Recent posts from the relay admin</Divider>