Convert to simple relay-based groups from nip29

This commit is contained in:
Jon Staab
2024-09-11 10:48:34 -07:00
parent ed365f7e38
commit 4ad67921a0
20 changed files with 363 additions and 525 deletions
+24 -19
View File
@@ -10,6 +10,7 @@
relays,
handles,
loadRelay,
db,
initStorage,
repository,
session,
@@ -27,7 +28,7 @@
import PrimaryNav from "@app/components/PrimaryNav.svelte"
import {modals, clearModal} from "@app/modal"
import {theme} from "@app/theme"
import {DEFAULT_RELAYS} from "@app/state"
import {INDEXER_RELAYS, topicsByUrl, relaysByMessage} from "@app/state"
import {loadUserData} from "@app/commands"
import * as state from "@app/state"
@@ -60,23 +61,27 @@
onMount(() => {
Object.assign(window, {get, state})
ready = initStorage('flotilla', 3, {
events: {
keyPath: "id",
store: createEventStore(repository),
},
relays: {
keyPath: "url",
store: relays,
},
handles: {
keyPath: "nip05",
store: handles,
},
publishStatus: storageAdapters.fromObjectStore(publishStatusData),
freshness: storageAdapters.fromObjectStore(freshness),
plaintext: storageAdapters.fromObjectStore(plaintext),
}).then(() => sleep(300)) // Wait an extra few ms because of repository throttle
ready = db
? Promise.resolve()
: initStorage("flotilla", 2, {
events: {
keyPath: "id",
store: createEventStore(repository),
},
relays: {
keyPath: "url",
store: relays,
},
handles: {
keyPath: "nip05",
store: handles,
},
topicsByUrl: storageAdapters.fromMapStore(topicsByUrl),
relaysByMessage: storageAdapters.fromMapStore(relaysByMessage),
publishStatus: storageAdapters.fromObjectStore(publishStatusData),
freshness: storageAdapters.fromObjectStore(freshness),
plaintext: storageAdapters.fromObjectStore(plaintext),
}).then(() => sleep(300)) // Wait an extra few ms because of repository throttle
dialog.addEventListener("close", () => {
if (modal) {
@@ -85,7 +90,7 @@
})
ready.then(() => {
for (const url of DEFAULT_RELAYS) {
for (const url of INDEXER_RELAYS) {
loadRelay(url)
}
+17 -29
View File
@@ -1,27 +1,20 @@
<script lang="ts">
import {onMount} from "svelte"
import Masonry from "svelte-bricks"
import {GROUP_META, displayRelayUrl} from "@welshman/util"
import {load, relays} from "@welshman/app"
import {displayRelayUrl} from "@welshman/util"
import {load, relaySearch} from "@welshman/app"
import Icon from "@lib/components/Icon.svelte"
import {makeSpacePath} from "@app/routes"
import {
displayGroup,
searchGroups,
relayUrlsByNom,
userMembership,
DEFAULT_RELAYS,
} from "@app/state"
import {userMembership, discoverRelays} from "@app/state"
let term = ""
$: groups = $searchGroups.searchOptions(term).filter(g => $relayUrlsByNom.get(g.nom)?.length > 0)
$: relays = $relaySearch.searchOptions(term)
onMount(() => {
load({
relays: [...DEFAULT_RELAYS, ...$relays.map(r => r.url)],
filters: [{kinds: [GROUP_META]}],
})
const sub = discoverRelays()
return () => sub.close()
})
</script>
@@ -34,26 +27,26 @@
</label>
<Masonry
animate={false}
items={groups}
items={relays}
minColWidth={250}
maxColWidth={800}
gap={16}
idKey="nom"
let:item={group}>
idKey="url"
let:item={relay}>
<a
href={makeSpacePath(group.nom)}
href={makeSpacePath(relay.url)}
class="card bg-base-100 shadow-xl transition-all hover:shadow-2xl hover:brightness-[1.1]">
<div class="center avatar mt-8">
<div
class="center relative !flex w-20 rounded-full border-2 border-solid border-base-300 bg-base-300">
{#if group.picture}
<img alt="" src={group.picture} />
{#if relay.profile?.icon}
<img alt="" src={relay.profile.icon} />
{:else}
<Icon icon="ghost" size={7} />
{/if}
</div>
</div>
{#if $userMembership?.noms.has(group.nom)}
{#if $userMembership?.topicsByUrl.has(relay.url)}
<div class="center absolute flex w-full">
<div
class="tooltip relative left-8 top-[38px] h-5 w-5 rounded-full bg-primary"
@@ -63,14 +56,9 @@
</div>
{/if}
<div class="card-body">
<h2 class="card-title justify-center">{displayGroup(group)}</h2>
<div class="text-center text-sm">
{#each $relayUrlsByNom.get(group.nom) || [] as url}
<div class="badge badge-neutral">{displayRelayUrl(url)}</div>
{/each}
</div>
{#if group.about}
<p class="py-4 text-sm">{group.about}</p>
<h2 class="card-title justify-center">{displayRelayUrl(relay.url)}</h2>
{#if relay.profile?.description}
<p class="py-4 text-sm text-center">{relay.profile.description}</p>
{/if}
</div>
</a>
+3 -14
View File
@@ -6,9 +6,9 @@
import {subscribe, loadRelay, relaySearch} from "@welshman/app"
import Button from "@lib/components/Button.svelte"
import Icon from "@lib/components/Icon.svelte"
import {DEFAULT_RELAYS, INDEXER_RELAYS} from "@app/state"
import {INDEXER_RELAYS, discoverRelays} from "@app/state"
const relays = readable(DEFAULT_RELAYS)
const relays = readable(INDEXER_RELAYS)
const removeRelay = (url: string) => null
@@ -17,18 +17,7 @@
let term = ""
onMount(() => {
const sub = subscribe({
filters: [{kinds: [30166], "#N": ["29"]}],
relays: [...INDEXER_RELAYS, ...DEFAULT_RELAYS],
})
sub.emitter.on("event", (url: string, event: SignedEvent) => {
const d = event.tags.find(t => t[0] === "d")?.[1] || ""
if (isShareableRelayUrl(d)) {
loadRelay(d)
}
})
const sub = discoverRelays()
return () => sub.close()
})
@@ -1,5 +1,8 @@
<script lang="ts">
import {nip19} from 'nostr-tools'
import {page} from "$app/stores"
import {sort} from '@welshman/lib'
import {displayRelayUrl} from '@welshman/util'
import {fly} from "@lib/transition"
import Icon from "@lib/components/Icon.svelte"
import Page from "@lib/components/Page.svelte"
@@ -11,8 +14,10 @@
import SecondaryNavSection from "@lib/components/SecondaryNavSection.svelte"
import SpaceExit from "@app/components/SpaceExit.svelte"
import SpaceJoin from "@app/components/SpaceJoin.svelte"
import {deriveGroup, userMembership, displayGroup} from "@app/state"
import RoomCreate from "@app/components/RoomCreate.svelte"
import {userMembership, decodeNEvent} from "@app/state"
import {pushModal} from "@app/modal"
import {makeSpacePath} from "@app/routes"
const openMenu = () => {
showMenu = true
@@ -22,22 +27,24 @@
showMenu = !showMenu
}
const leaveSpace = () => pushModal(SpaceExit, {nom})
const leaveSpace = () => pushModal(SpaceExit, {url})
const joinSpace = () => pushModal(SpaceJoin, {nom})
const joinSpace = () => pushModal(SpaceJoin, {url})
const addRoom = () => pushModal(RoomCreate, {url})
let showMenu = false
$: nom = $page.params.nom
$: group = deriveGroup(nom)
$: url = decodeNEvent($page.params.nrelay)
$: rooms = sort($userMembership?.topicsByUrl?.get(url) || [])
</script>
{#key nom}
{#key url}
<SecondaryNav>
<SecondaryNavSection>
<div>
<SecondaryNavItem class="w-full !justify-between" on:click={openMenu}>
<strong>{displayGroup($group)}</strong>
<strong>{displayRelayUrl(url)}</strong>
<Icon icon="alt-arrow-down" />
</SecondaryNavItem>
{#if showMenu}
@@ -45,7 +52,7 @@
<ul
transition:fly|local
class="menu absolute z-popover mt-2 w-full rounded-box bg-base-100 p-2 shadow-xl">
{#if $userMembership?.noms.has(nom)}
{#if $userMembership?.topicsByUrl.has(url)}
<li class="text-error">
<Button on:click={leaveSpace}>
<Icon icon="exit" />
@@ -66,22 +73,22 @@
</div>
<div class="my-3 h-px bg-base-200" />
<div in:fly|local>
<SecondaryNavItem href="/spaces/{nom}">
<SecondaryNavItem href={makeSpacePath(url)}>
<Icon icon="chat-round" /> Chat
</SecondaryNavItem>
</div>
<div in:fly|local={{delay: 50}}>
<SecondaryNavItem href="/spaces/{nom}/threads">
<SecondaryNavItem href={makeSpacePath(url, "threads")}>
<Icon icon="notes-minimalistic" /> Threads
</SecondaryNavItem>
</div>
<div in:fly|local={{delay: 100}}>
<SecondaryNavItem href="/spaces/{nom}/events">
<SecondaryNavItem href={makeSpacePath(url, "events")}>
<Icon icon="calendar-minimalistic" /> Calendar
</SecondaryNavItem>
</div>
<div in:fly|local={{delay: 150}}>
<SecondaryNavItem href="/spaces/{nom}/listings">
<SecondaryNavItem href={makeSpacePath(url, "listings")}>
<Icon icon="shop-minimalistic" /> Market
</SecondaryNavItem>
</div>
@@ -89,11 +96,18 @@
<div class="h-2" />
<SecondaryNavHeader>
Rooms
<Button on:click={() => alert("Uh, I don't know how to do rooms on NIP 29")}>
<Button on:click={addRoom}>
<Icon icon="add-circle" />
</Button>
</SecondaryNavHeader>
</div>
{#each rooms as topic, i (topic)}
<div transition:fly|local={{delay: 250 + i * 50}}>
<SecondaryNavItem href={makeSpacePath(url, topic)}>
<Icon icon="hashtag" /> {topic}
</SecondaryNavItem>
</div>
{/each}
</SecondaryNavSection>
</SecondaryNav>
<Page>
@@ -11,16 +11,16 @@
import {onMount} from "svelte"
import {page} from "$app/stores"
import {sortBy, now} from "@welshman/lib"
import type {TrustedEvent} from "@welshman/util"
import type {TrustedEvent, Filter} from "@welshman/util"
import {subscribe, formatTimestampAsDate} from "@welshman/app"
import Icon from "@lib/components/Icon.svelte"
import Spinner from "@lib/components/Spinner.svelte"
import GroupNote from "@app/components/GroupNote.svelte"
import GroupCompose from "@app/components/GroupCompose.svelte"
import {deriveGroupChat, userRelayUrlsByNom} from "@app/state"
import {deriveChat, userMembership, MESSAGE, REPLY} from "@app/state"
const {nom} = $page.params
const chat = deriveGroupChat(nom)
const {url, topic} = $page.params
const chat = deriveChat(url)
const assertEvent = (e: any) => e as TrustedEvent
@@ -60,10 +60,10 @@
}, 3000)
onMount(() => {
const sub = subscribe({
filters: [{"#h": [nom], since: now() - 30}],
relays: $userRelayUrlsByNom.get(nom) || [],
})
const since = now() - 30
const kinds = [MESSAGE, REPLY]
const filter = topic ? {kinds, since, "#t": [topic]} : {kinds, since} as Filter
const sub = subscribe({filters: [filter], relays: [url]})
return () => sub.close()
})
@@ -100,5 +100,5 @@
</Spinner>
</p>
</div>
<GroupCompose {nom} />
<GroupCompose {url} {topic} />
</div>