Re-work rooms derivation

This commit is contained in:
Jon Staab
2025-10-30 15:52:24 -07:00
parent a324dad2ba
commit 07660c9d44
3 changed files with 41 additions and 42 deletions

View File

@@ -22,7 +22,7 @@
{:else} {:else}
<img alt="Room icon" {src} class="h-6 w-6 rounded-lg" /> <img alt="Room icon" {src} class="h-6 w-6 rounded-lg" />
{/if} {/if}
{:else if $room?.closed || $room?.private} {:else if $room?.isClosed || $room?.isPrivate}
<Icon icon={Lock} /> <Icon icon={Lock} />
{:else} {:else}
<Icon icon={Hashtag} /> <Icon icon={Hashtag} />

View File

@@ -4,6 +4,8 @@ import {get, derived, writable} from "svelte/store"
import * as nip19 from "nostr-tools/nip19" import * as nip19 from "nostr-tools/nip19"
import { import {
on, on,
gt,
max,
spec, spec,
call, call,
first, first,
@@ -17,7 +19,6 @@ import {
pushToMapKey, pushToMapKey,
shuffle, shuffle,
parseJson, parseJson,
fromPairs,
memoize, memoize,
addToMapKey, addToMapKey,
identity, identity,
@@ -88,7 +89,6 @@ import {
getPubkeyTagValues, getPubkeyTagValues,
getRelaysFromList, getRelaysFromList,
getRelayTagValues, getRelayTagValues,
getTag,
getTagValue, getTagValue,
getTagValues, getTagValues,
isRelayUrl, isRelayUrl,
@@ -97,8 +97,16 @@ import {
readList, readList,
RelayMode, RelayMode,
verifyEvent, verifyEvent,
readRoomMeta,
} from "@welshman/util"
import type {
TrustedEvent,
RelayProfile,
PublishedList,
PublishedRoomMeta,
List,
Filter,
} from "@welshman/util" } from "@welshman/util"
import type {TrustedEvent, RelayProfile, PublishedList, List, Filter} from "@welshman/util"
import {decrypt} from "@welshman/signer" import {decrypt} from "@welshman/signer"
import {routerContext, Router} from "@welshman/router" import {routerContext, Router} from "@welshman/router"
import { import {
@@ -534,16 +542,9 @@ export const chatSearch = derived(chats, $chats =>
export const messages = deriveEvents(repository, {filters: [{kinds: [MESSAGE]}]}) export const messages = deriveEvents(repository, {filters: [{kinds: [MESSAGE]}]})
export type Room = { export type Room = PublishedRoomMeta & {
id: string id: string
url: string url: string
h: string
name: string
event: TrustedEvent
closed: boolean
private: boolean
picture?: string
about?: string
} }
export const makeRoomId = (url: string, h: string) => `${url}'${h}` export const makeRoomId = (url: string, h: string) => `${url}'${h}`
@@ -553,39 +554,37 @@ export const splitRoomId = (id: string) => id.split("'")
export const hasNip29 = (relay?: RelayProfile) => export const hasNip29 = (relay?: RelayProfile) =>
relay?.supported_nips?.map?.(String)?.includes?.("29") relay?.supported_nips?.map?.(String)?.includes?.("29")
export const roomMetas = deriveEventsMapped<PublishedRoomMeta>(repository, {
filters: [{kinds: [ROOM_META]}],
itemToEvent: item => item.event,
eventToItem: readRoomMeta,
})
export const roomDeletes = deriveEvents(repository, {
filters: [{kinds: [ROOM_DELETE]}],
})
export const rooms = derived( export const rooms = derived(
[deriveEvents(repository, {filters: [{kinds: [ROOM_META, ROOM_DELETE]}]}), getUrlsForEvent], [roomMetas, roomDeletes, getUrlsForEvent],
([$events, $getUrlsForEvent]) => { ([$roomMetas, $roomDeletes, $getUrlsForEvent]) => {
const result = new Map<string, Room>() const result = new Map<string, Room>()
const deletedByH = new Map<string, number>()
for (const event of sortBy(e => e.created_at, $events)) { for (const event of $roomDeletes) {
for (const url of $getUrlsForEvent(event.id)) { for (const h of getTagValues("h", event.tags)) {
if (event.kind === ROOM_META) { deletedByH.set(h, max([deletedByH.get(h), event.created_at]))
const meta = fromPairs(event.tags) }
const h = meta.d }
if (h) { for (const meta of $roomMetas) {
const id = makeRoomId(url, h) if (gt(deletedByH.get(meta.h), meta.event.created_at)) {
continue
}
result.set(id, { for (const url of $getUrlsForEvent(meta.event.id)) {
id, const id = makeRoomId(url, meta.h)
url,
h,
event,
name: meta.name || h,
closed: Boolean(getTag("closed", event.tags)),
private: Boolean(getTag("private", event.tags)),
picture: meta.picture,
about: meta.about,
})
}
}
if (event.kind === ROOM_DELETE) { result.set(id, {...meta, url, id})
for (const h of getTagValues("h", event.tags)) {
result.delete(makeRoomId(url, h))
}
}
} }
} }

View File

@@ -386,7 +386,7 @@
<PageContent bind:element onscroll={onScroll} class="flex flex-col-reverse pt-4"> <PageContent bind:element onscroll={onScroll} class="flex flex-col-reverse pt-4">
<div bind:this={dynamicPadding}></div> <div bind:this={dynamicPadding}></div>
{#if $room?.private && $membershipStatus !== MembershipStatus.Granted} {#if $room?.isPrivate && $membershipStatus !== MembershipStatus.Granted}
<div class="py-20"> <div class="py-20">
<div class="card2 col-8 m-auto max-w-md items-center text-center"> <div class="card2 col-8 m-auto max-w-md items-center text-center">
<p class="row-2">You aren't currently a member of this room.</p> <p class="row-2">You aren't currently a member of this room.</p>
@@ -450,9 +450,9 @@
</PageContent> </PageContent>
<div class="chat__compose bg-base-200" bind:this={chatCompose}> <div class="chat__compose bg-base-200" bind:this={chatCompose}>
{#if $room?.private && $membershipStatus !== MembershipStatus.Granted} {#if $room?.isPrivate && $membershipStatus !== MembershipStatus.Granted}
<!-- pass --> <!-- pass -->
{:else if $room?.closed && $membershipStatus !== MembershipStatus.Granted} {:else if $room?.isClosed && $membershipStatus !== MembershipStatus.Granted}
<div class="bg-alt card m-4 flex flex-row items-center justify-between px-4 py-3"> <div class="bg-alt card m-4 flex flex-row items-center justify-between px-4 py-3">
<p>Only members are allowed to post to this room.</p> <p>Only members are allowed to post to this room.</p>
{#if $membershipStatus === MembershipStatus.Pending} {#if $membershipStatus === MembershipStatus.Pending}