Add room deletion

This commit is contained in:
Jon Staab
2025-10-24 13:36:59 -07:00
parent 0e94a9c33f
commit 0b98197a86
7 changed files with 173 additions and 110 deletions
+54 -28
View File
@@ -70,7 +70,9 @@ import {
ROOM_JOIN,
ROOM_LEAVE,
ROOM_MEMBERS,
ROOM_ADMINS,
ROOM_META,
ROOM_DELETE,
ROOM_REMOVE_MEMBER,
ROOMS,
THREAD,
@@ -278,8 +280,11 @@ export const deriveEventsForUrl = (url: string, filters: Filter[]) =>
})
export const deriveSignedEventsForUrl = (url: string, filters: Filter[]) =>
derived([deriveEventsForUrl(url, filters), deriveRelay(url)], ([$events, $relay]) =>
$relay?.self ? $events.filter(spec({pubkey: $relay.self})) : [],
derived(
[deriveEventsForUrl(url, filters), deriveRelay(url)],
([$events, $relay]) => $events,
// Disable this check for now since khatru doesn't support self
// $relay?.self ? $events.filter(spec({pubkey: $relay.self})) : [],
)
// Context
@@ -559,37 +564,43 @@ export const splitChannelId = (id: string) => id.split("'")
export const hasNip29 = (relay?: RelayProfile) =>
relay?.supported_nips?.map?.(String)?.includes?.("29")
export const channelEvents = deriveEvents(repository, {filters: [{kinds: [ROOM_META]}]})
export const channels = derived(
[channelEvents, getUrlsForEvent],
([$channelEvents, $getUrlsForEvent]) => {
const $channels: Channel[] = []
[deriveEvents(repository, {filters: [{kinds: [ROOM_META, ROOM_DELETE]}]}), getUrlsForEvent],
([$events, $getUrlsForEvent]) => {
const result = new Map<string, Channel>()
for (const event of $channelEvents) {
const meta = fromPairs(event.tags)
const room = meta.d
for (const event of sortBy(e => e.created_at, $events)) {
for (const url of $getUrlsForEvent(event.id)) {
if (event.kind === ROOM_META) {
const meta = fromPairs(event.tags)
const room = meta.d
if (room) {
for (const url of $getUrlsForEvent(event.id)) {
const id = makeChannelId(url, room)
if (room) {
const id = makeChannelId(url, room)
$channels.push({
id,
url,
room,
event,
name: meta.name || room,
closed: Boolean(getTag("closed", event.tags)),
private: Boolean(getTag("private", event.tags)),
picture: meta.picture,
about: meta.about,
})
result.set(id, {
id,
url,
room,
event,
name: meta.name || room,
closed: Boolean(getTag("closed", event.tags)),
private: Boolean(getTag("private", event.tags)),
picture: meta.picture,
about: meta.about,
})
}
}
if (event.kind === ROOM_DELETE) {
for (const room of getTagValues("h", event.tags)) {
result.delete(makeChannelId(url, room))
}
}
}
}
return uniqBy(c => c.id, $channels)
return Array.from(result.values())
},
)
@@ -745,7 +756,7 @@ export const deriveSpaceMembers = (url: string) =>
const members = new Set()
for (const event of $events) {
for (const event of sortBy(e => e.created_at, $events)) {
const pubkeys = getPubkeyTagValues(event.tags)
if (event.kind === RELAY_ADD_MEMBER) {
@@ -768,7 +779,8 @@ export const deriveSpaceMembers = (url: string) =>
export const deriveRoomMembers = (url: string, room: string) =>
derived(
deriveEventsForUrl(url, [
{kinds: [ROOM_ADD_MEMBER, ROOM_REMOVE_MEMBER, ROOM_MEMBERS], "#h": [room]},
{kinds: [ROOM_MEMBERS], "#d": [room]},
{kinds: [ROOM_ADD_MEMBER, ROOM_REMOVE_MEMBER], "#h": [room]},
]),
$events => {
const membersEvent = $events.find(spec({kind: ROOM_MEMBERS}))
@@ -779,7 +791,7 @@ export const deriveRoomMembers = (url: string, room: string) =>
const members = new Set()
for (const event of $events) {
for (const event of sortBy(e => -e.created_at, $events)) {
const pubkeys = getPubkeyTagValues(event.tags)
if (event.kind === ROOM_ADD_MEMBER) {
@@ -799,6 +811,17 @@ export const deriveRoomMembers = (url: string, room: string) =>
},
)
export const deriveRoomAdmins = (url: string, room: string) =>
derived(deriveEventsForUrl(url, [{kinds: [ROOM_ADMINS], "#d": [room]}]), $events => {
const adminsEvent = first($events)
if (adminsEvent) {
return getPubkeyTagValues(adminsEvent.tags)
}
return []
})
// User membership status
export enum MembershipStatus {
@@ -873,6 +896,9 @@ export const deriveUserCanCreateRoom = (url: string) =>
},
)
export const deriveUserIsRoomAdmin = (url: string, room: string) =>
derived([pubkey, deriveRoomAdmins(url, room)], ([$pubkey, $admins]) => $admins.includes($pubkey!))
// Other utils
export const encodeRelay = (url: string) =>
+12 -3
View File
@@ -19,8 +19,13 @@ import {
getRelayTagValues,
WRAP,
ROOM_META,
ROOM_DELETE,
ROOM_ADMINS,
ROOM_MEMBERS,
ROOM_ADD_MEMBER,
ROOM_REMOVE_MEMBER,
ROOM_CREATE_PERMISSION,
RELAY_MEMBERS,
isSignedEvent,
} from "@welshman/util"
import type {Filter, TrustedEvent} from "@welshman/util"
@@ -165,12 +170,14 @@ const syncUserData = () => {
const syncMembership = (url: string) => {
const controller = new AbortController()
const relayFilter = {kinds: [RELAY_MEMBERS, ROOM_CREATE_PERMISSION]}
const roomsFilter = {kinds: [ROOM_ADMINS, ROOM_MEMBERS, ROOM_META, ROOM_DELETE]}
// Load group metadata
// Load group metadata and member lists
pullConservatively({
relays: [url],
signal: controller.signal,
filters: [{kinds: [ROOM_META]}],
filters: [relayFilter, roomsFilter],
})
// Load historical data from up to a month ago for quick page loading
@@ -184,7 +191,9 @@ const syncMembership = (url: string) => {
request({
relays: [url],
signal: controller.signal,
filters: [MESSAGE_FILTER, COMMENT_FILTER, MEMBERSHIP_FILTER].map(assoc("since", now())),
filters: [relayFilter, roomsFilter, MESSAGE_FILTER, COMMENT_FILTER, MEMBERSHIP_FILTER].map(
assoc("since", now()),
),
})
return () => controller.abort()