From 7c9b191bdd4dfd4377c7c0f81b621d1d026b2060 Mon Sep 17 00:00:00 2001 From: Jon Staab Date: Tue, 17 Mar 2026 16:57:31 -0700 Subject: [PATCH 1/2] Update closed room behavior --- src/app/components/RoomForm.svelte | 2 +- src/app/core/requests.ts | 13 +++-- src/app/core/state.ts | 5 +- src/routes/spaces/[relay]/[h]/+page.svelte | 60 ++++++++++------------ 4 files changed, 42 insertions(+), 38 deletions(-) diff --git a/src/app/components/RoomForm.svelte b/src/app/components/RoomForm.svelte index 042aaf76..77e6577d 100644 --- a/src/app/components/RoomForm.svelte +++ b/src/app/components/RoomForm.svelte @@ -208,7 +208,7 @@
- Ignore requests to join + Require admins to approve join requests
{@render footer({loading})} diff --git a/src/app/core/requests.ts b/src/app/core/requests.ts index b5e0cedb..b1d8da43 100644 --- a/src/app/core/requests.ts +++ b/src/app/core/requests.ts @@ -47,10 +47,10 @@ export const makeFeed = ({ onForwardExhausted?: () => void at?: number }) => { - const interval = int(WEEK) const controller = new AbortController() const events = writable([]) + let interval = int(WEEK) let buffer: TrustedEvent[] = [] let backwardWindow = [at - interval, at] let forwardWindow = [at, at + interval] @@ -111,13 +111,20 @@ export const makeFeed = ({ }), ] - const loadTimeframe = (since: number, until: number) => { - request({ + const loadTimeframe = async (since: number, until: number) => { + const events = await request({ relays: [url], autoClose: true, signal: controller.signal, filters: filters.map(filter => ({...filter, since, until})), }) + + // If we found nothing, accelerate + if (events.length === 0) { + interval = Math.round(interval * 1.1) + } else { + interval = int(WEEK) + } } const backwardScroller = createScroller({ diff --git a/src/app/core/state.ts b/src/app/core/state.ts index 04a7751b..bab2a17b 100644 --- a/src/app/core/state.ts +++ b/src/app/core/state.ts @@ -111,6 +111,7 @@ import { readRoomMeta, makeRoomMeta, ManagementMethod, + sortEventsAsc, sortEventsDesc, getAddress, Address, @@ -287,7 +288,7 @@ export const deriveRelaySignedEvents = (url: string, filters: Filter[] = [{}]) = derived( [deriveRelay(url), deriveEventsForUrl(url, filters)], ([relay, events]) => events, - // khatru doesn't support relay.self, uncomment when it's ready + // TODO: khatru doesn't support relay.self, uncomment when it's ready // filter(spec({pubkey: relay.self}), events) ) @@ -868,7 +869,7 @@ export const deriveRoomMembers = (url: string, h: string) => { const members = new Set() - for (const event of sortBy(e => -e.created_at, $events)) { + for (const event of sortEventsAsc($events)) { const pubkeys = getPubkeyTagValues(event.tags) if (event.kind === ROOM_ADD_MEMBER) { diff --git a/src/routes/spaces/[relay]/[h]/+page.svelte b/src/routes/spaces/[relay]/[h]/+page.svelte index 7f54c610..2b139c4d 100644 --- a/src/routes/spaces/[relay]/[h]/+page.svelte +++ b/src/routes/spaces/[relay]/[h]/+page.svelte @@ -381,22 +381,20 @@

You aren't currently a member of this room.

- {#if !$room.isClosed} - {#if $membershipStatus === MembershipStatus.Pending} - - {:else} - - {/if} + {#if $membershipStatus === MembershipStatus.Pending} + + {:else} + {/if}
@@ -456,22 +454,20 @@ {:else if $room.isRestricted && $membershipStatus !== MembershipStatus.Granted}

Only members are allowed to post to this room.

- {#if !$room.isClosed} - {#if $membershipStatus === MembershipStatus.Pending} - - {:else} - - {/if} + {#if $membershipStatus === MembershipStatus.Pending} + + {:else} + {/if}
{:else} -- 2.52.0 From b100ec124c1deb9f81ab24d5ea3d41e03be335fa Mon Sep 17 00:00:00 2001 From: Jon Staab Date: Tue, 17 Mar 2026 17:16:01 -0700 Subject: [PATCH 2/2] Migrate Reports dialog to ActionItems dialog, add room join requests to queue --- AGENTS.md | 1 + src/app/components/ProfileDetail.svelte | 6 +- src/app/components/ReportItem.svelte | 6 +- src/app/components/RoomForm.svelte | 2 +- src/app/components/RoomJoinItem.svelte | 83 ++++++++++++++++++++ src/app/components/RoomMembersAdd.svelte | 39 +++------ src/app/components/SpaceActionItems.svelte | 58 ++++++++++++++ src/app/components/SpaceMembersAdd.svelte | 25 ++---- src/app/components/SpaceMembersBanned.svelte | 6 +- src/app/components/SpaceMenu.svelte | 26 +++--- src/app/core/commands.ts | 56 ++++++++++++- src/app/core/state.ts | 46 +++++++++++ src/app/core/sync.ts | 9 +-- 13 files changed, 285 insertions(+), 78 deletions(-) create mode 100644 src/app/components/RoomJoinItem.svelte create mode 100644 src/app/components/SpaceActionItems.svelte diff --git a/AGENTS.md b/AGENTS.md index 0ff74656..0939c90b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -169,6 +169,7 @@ src/ - When creating forms, use `FieldInline` or `Field` instead of custom elements/tailwindcss - Do not define svelte event handlers inline, instead name them and put them in the script section of templates - Avoid using `as`, except where necessary. Instead, annotate function parameters, and ensure upstream values are typed correctly. +- Instead of `getTag(tagName, event.tags)?.[1] || ""`, use `getTagValue(tagName, event.tags)` **Human-First Simplicity (Jon Staab Style):** diff --git a/src/app/components/ProfileDetail.svelte b/src/app/components/ProfileDetail.svelte index 7a85105f..0c7484ee 100644 --- a/src/app/components/ProfileDetail.svelte +++ b/src/app/components/ProfileDetail.svelte @@ -30,6 +30,7 @@ import EventInfo from "@app/components/EventInfo.svelte" import ProfileBadges from "@app/components/ProfileBadges.svelte" import {pubkeyLink, deriveUserIsSpaceAdmin, deriveSpaceBannedPubkeyItems} from "@app/core/state" + import {addSpaceMembers} from "@app/core/commands" import {pushModal} from "@app/util/modal" import {pushToast} from "@app/util/toast" import {makeChatPath} from "@app/util/routes" @@ -85,10 +86,7 @@ }) const restoreMember = async () => { - const {error} = await manageRelay(url!, { - method: ManagementMethod.AllowPubkey, - params: [pubkey], - }) + const error = await addSpaceMembers(url!, [pubkey]) if (error) { pushToast({theme: "error", message: error}) diff --git a/src/app/components/ReportItem.svelte b/src/app/components/ReportItem.svelte index 3faecb1e..8d8a9a57 100644 --- a/src/app/components/ReportItem.svelte +++ b/src/app/components/ReportItem.svelte @@ -15,10 +15,10 @@ type Props = { url: string event: TrustedEvent - onDelete?: () => void + onResolved?: () => void } - const {url, event, onDelete}: Props = $props() + const {url, event, onResolved}: Props = $props() const etag = getTag("e", event.tags) const ptag = getTag("p", event.tags) @@ -45,7 +45,7 @@ {/if} - + {#if event.content}
diff --git a/src/app/components/RoomForm.svelte b/src/app/components/RoomForm.svelte index 77e6577d..218feb74 100644 --- a/src/app/components/RoomForm.svelte +++ b/src/app/components/RoomForm.svelte @@ -208,7 +208,7 @@
- Require admins to approve join requests + Membership requires approval
{@render footer({loading})} diff --git a/src/app/components/RoomJoinItem.svelte b/src/app/components/RoomJoinItem.svelte new file mode 100644 index 00000000..7c7c2020 --- /dev/null +++ b/src/app/components/RoomJoinItem.svelte @@ -0,0 +1,83 @@ + + +
+
+
+ + + requested membership in # + +
+
+ + +
+
+
diff --git a/src/app/components/RoomMembersAdd.svelte b/src/app/components/RoomMembersAdd.svelte index 3336132a..63397e3d 100644 --- a/src/app/components/RoomMembersAdd.svelte +++ b/src/app/components/RoomMembersAdd.svelte @@ -2,9 +2,8 @@ import {onMount} from "svelte" import {setKey, popKey} from "@lib/implicit" import {sleep} from "@welshman/lib" - import {ManagementMethod} from "@welshman/util" - import {manageRelay} from "@welshman/app" - import {addRoomMember, displayProfileByPubkey, waitForThunkError} from "@welshman/app" + import {displayProfileByPubkey} from "@welshman/app" + import type {PublishedRoomMeta} from "@welshman/util" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import Spinner from "@lib/components/Spinner.svelte" import Button from "@lib/components/Button.svelte" @@ -22,6 +21,7 @@ import {pushToast} from "@app/util/toast" import {pushModal} from "@app/util/modal" import {deriveRoom, deriveSpaceMembers} from "@app/core/state" + import {addRoomMembers} from "@app/core/commands" interface Props { url: string @@ -42,35 +42,14 @@ // Show loading for auto submit callback await sleep(500) - const results = await Promise.all( - pubkeys - .filter(pubkey => !$spaceMembers.includes(pubkey)) - .map(pubkey => - manageRelay(url, { - method: ManagementMethod.AllowPubkey, - params: [pubkey], - }), - ), - ) + const error = await addRoomMembers(url, $room as PublishedRoomMeta, pubkeys) - for (const {error} of results) { - if (error) { - return pushToast({theme: "error", message: error}) - } + if (error) { + pushToast({theme: "error", message: error}) + } else { + pushToast({message: "Members have successfully been added!"}) + back() } - - const errors = await Promise.all( - pubkeys.map(pubkey => waitForThunkError(addRoomMember(url, $room, pubkey))), - ) - - for (const error of errors) { - if (error) { - return pushToast({theme: "error", message: errors[0]}) - } - } - - pushToast({message: "Members have successfully been added!"}) - back() } finally { loading = false } diff --git a/src/app/components/SpaceActionItems.svelte b/src/app/components/SpaceActionItems.svelte new file mode 100644 index 00000000..55c45a24 --- /dev/null +++ b/src/app/components/SpaceActionItems.svelte @@ -0,0 +1,58 @@ + + + + + + Action Items + on + +
+ {#each $actionItems as event (event.id)} + {#if event.kind === REPORT} + + {:else} + + {/if} + {:else} +

No action items found.

+ {/each} +
+
+ + + +
diff --git a/src/app/components/SpaceMembersAdd.svelte b/src/app/components/SpaceMembersAdd.svelte index 23dc5b4d..4df724c9 100644 --- a/src/app/components/SpaceMembersAdd.svelte +++ b/src/app/components/SpaceMembersAdd.svelte @@ -1,6 +1,5 @@