Add some state management stuff

This commit is contained in:
Jon Staab
2024-08-06 15:46:37 -07:00
parent 36a920df51
commit fb04a68168
18 changed files with 5474 additions and 5206 deletions
+38
View File
@@ -0,0 +1,38 @@
import type {SignedEvent} from "@welshman/util"
import {Repository, Relay} from "@welshman/util"
import {NetworkContext, Tracker} from "@welshman/net"
export const DUFFLEPUD_URL = "https://dufflepud.onrender.com"
export const repository = new Repository()
export const relay = new Relay(repository)
export const tracker = new Tracker()
const seenChallenges = new Set()
Object.assign(NetworkContext, {
onEvent: (url: string, event: SignedEvent) => tracker.track(event.id, url),
isDeleted: (url: string, event: SignedEvent) => repository.isDeleted(event),
// onAuth: async (url, challenge) => {
// if (seenChallenges.has(challenge)) {
// return
// }
// seenChallenges.add(challenge)
// const event = await signer.get().signAsUser(
// createEvent(22242, {
// tags: [
// ["relay", url],
// ["challenge", challenge],
// ],
// }),
// )
// NetworkContext.pool.get(url).send(["AUTH", event])
// return event
// },
})
+15
View File
@@ -0,0 +1,15 @@
import {batch, postJson} from "@welshman/lib"
import {normalizeRelayUrl} from "@welshman/util"
import {relayInfo} from "app/state"
export const loadRelay = batch(1000, async (urls: string[]) => {
const data = await postJson(`${DUFFLEPUD_URL}/relay/info`, {urls})
relayInfo.update($relayInfo => {
for (const {url, info} of data) {
$relayInfo.set(normalizeRelayUrl(url), info)
}
return $relayInfo
})
})
+6 -3
View File
@@ -8,7 +8,8 @@
<script lang="ts">
import Icon from "@lib/components/Icon.svelte"
import PrimaryNavItem from "@lib/components/PrimaryNavItem.svelte"
import {spaces} from "@app/state"
import {getGroupName, getGroupPicture, makeGroupId} from "@app/domain"
import {userGroupRelaysByNom, groupsById} from "@app/state"
</script>
<div class="relative w-14 bg-base-100">
@@ -22,10 +23,12 @@
src="https://img.daisyui.com/images/stock/photo-1534528741775-53994a69daeb.webp" />
</div>
</PrimaryNavItem>
{#each $spaces as { id, name, picture } (id)}
{#each $userGroupRelaysByNom.entries() as [nom, relays] (nom)}
{@const event = $groupsById.get(makeGroupId(relays[0], nom))}
{@const name = getGroupName(event)}
<PrimaryNavItem title={name}>
<div class="w-10 rounded-full border border-solid border-base-300">
<img alt={name} src={picture} />
<img alt={name} src={getGroupPicture(event)} />
</div>
</PrimaryNavItem>
{/each}
+1 -1
View File
@@ -4,7 +4,7 @@
</script>
<div class="flex w-60 flex-col gap-1 bg-base-300 px-2 py-4">
<SecondaryNavItem href="/">
<SecondaryNavItem href="/home">
<Icon icon="home-smile" /> Home
</SecondaryNavItem>
<SecondaryNavItem href="/people">
+22
View File
@@ -0,0 +1,22 @@
import {stripProtocol} from "@welshman/lib"
import type {TrustedEvent} from "@welshman/util"
import {getIdentifier, normalizeRelayUrl} from "@welshman/util"
export const GROUP_DELIMITER = `'`
export const makeGroupId = (url: string, nom: string) =>
[stripProtocol(url), nom].join(GROUP_DELIMITER)
export const getGroupNom = (e: TrustedEvent) => getIdentifier(e)?.split(GROUP_DELIMITER)[1]
export const getGroupUrl = (e: TrustedEvent) => {
const id = getIdentifier(e)
const url = id?.split(GROUP_DELIMITER)[0]
return url ? normalizeRelayUrl(url) : null
}
export const getGroupName = (e: TrustedEvent | undefined) => e?.tags.find(t => t[0] === "name")?.[1]
export const getGroupPicture = (e: TrustedEvent | undefined) =>
e?.tags.find(t => t[0] === "picture")?.[1]
-1
View File
@@ -1,5 +1,4 @@
import type {ComponentType} from "svelte"
import {readable, writable} from "svelte/store"
import {randomId} from "@welshman/lib"
import {pushState} from "$app/navigation"
+43 -9
View File
@@ -1,10 +1,44 @@
import {readable} from "svelte/store"
import {writable, derived} from "svelte/store"
import {pushToMapKey, indexBy} from "@welshman/lib"
import {getIdentifier, GROUP_META, GROUPS, getGroupTagValues} from "@welshman/util"
import {deriveEvents} from "@welshman/store"
import {repository} from "@app/base"
import {getGroupUrl, GROUP_DELIMITER} from "@app/domain"
export const spaces = readable([
{
id: "test",
name: "Test",
picture:
"https://images.unsplash.com/photo-1721853046219-209921be684e?w=800&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxmZWF0dXJlZC1waG90b3MtZmVlZHw0fHx8ZW58MHx8fHx8",
},
])
export const pk = writable<string | null>(null)
export const sessions = writable(new Map())
export const session = derived([pk, sessions], ([$pk, $sessions]) => $sessions.get($pk))
export const relayInfo = writable(new Map())
export const groupEvents = deriveEvents(repository, {
filters: [{kinds: [GROUP_META]}],
})
export const groups = derived([relayInfo, groupEvents], ([$relayInfo, $groupEvents]) =>
$groupEvents.filter(e => $relayInfo.get(getGroupUrl(e))?.pubkey === e.pubkey),
)
export const groupsById = derived(groups, $groups => indexBy(getIdentifier, $groups))
export const groupsEvents = deriveEvents(repository, {
filters: [{kinds: [GROUPS]}],
})
export const userGroupsEvent = derived([pk, groupsEvents], ([$pk, $groupsEvents]) =>
$groupsEvents.find(e => e.pubkey === $pk),
)
export const userGroupRelaysByNom = derived(userGroupsEvent, $userGroupsEvent => {
const relaysByNom = new Map()
for (const id of getGroupTagValues($userGroupsEvent?.tags || [])) {
const [relay, nom] = id.split(GROUP_DELIMITER)
pushToMapKey(relaysByNom, nom, relay)
}
return relaysByNom
})