From 0dab2cc7796480505bc0d20a3037a919f7eb6cdd Mon Sep 17 00:00:00 2001 From: Jon Staab Date: Sat, 29 Aug 2026 09:19:01 -0700 Subject: [PATCH] Add feed context to improve performance of ReactionSummary --- src/app/components/ArticleActions.svelte | 12 +- src/app/components/ArticleItem.svelte | 6 +- .../components/CalendarEventActions.svelte | 12 +- src/app/components/CalendarEventItem.svelte | 6 +- src/app/components/Chat.svelte | 11 +- src/app/components/ChatMessage.svelte | 6 +- src/app/components/ClassifiedActions.svelte | 12 +- src/app/components/ClassifiedItem.svelte | 6 +- src/app/components/CommentActions.svelte | 12 +- src/app/components/CommentTree.svelte | 8 +- src/app/components/EventComments.svelte | 6 +- src/app/components/GoalActions.svelte | 12 +- src/app/components/GoalItem.svelte | 6 +- src/app/components/NoteItem.svelte | 12 +- src/app/components/PinContentEvent.svelte | 7 +- src/app/components/PollActions.svelte | 12 +- src/app/components/PollItem.svelte | 6 +- src/app/components/ProfileFeed.svelte | 10 +- src/app/components/ProfileLatest.svelte | 8 +- src/app/components/ProfilePageNotes.svelte | 11 +- src/app/components/ReactionSummary.svelte | 61 ++---- src/app/components/RecentItem.svelte | 18 +- src/app/components/RoomChat.svelte | 8 +- src/app/components/RoomItem.svelte | 13 +- src/app/components/SpaceRecentSummary.svelte | 7 +- src/app/components/ThreadActions.svelte | 12 +- src/app/components/ThreadItem.svelte | 6 +- src/app/components/ThreadPost.svelte | 8 +- src/app/content.ts | 2 + src/app/feeds.ts | 173 +++++++++++++++++- .../spaces/[relay]/articles/+page.svelte | 14 +- .../[relay]/articles/[address]/+page.svelte | 9 +- .../spaces/[relay]/calendar/+page.svelte | 14 +- .../[relay]/calendar/[address]/+page.svelte | 9 +- .../spaces/[relay]/classifieds/+page.svelte | 14 +- .../classifieds/[address]/+page.svelte | 9 +- src/routes/spaces/[relay]/goals/+page.svelte | 14 +- .../spaces/[relay]/goals/[id]/+page.svelte | 9 +- src/routes/spaces/[relay]/polls/+page.svelte | 14 +- .../spaces/[relay]/polls/[id]/+page.svelte | 10 +- src/routes/spaces/[relay]/recent/+page.svelte | 8 +- .../spaces/[relay]/threads/[id]/+page.svelte | 8 +- 42 files changed, 468 insertions(+), 153 deletions(-) diff --git a/src/app/components/ArticleActions.svelte b/src/app/components/ArticleActions.svelte index 5dccb73b..e4aa19da 100644 --- a/src/app/components/ArticleActions.svelte +++ b/src/app/components/ArticleActions.svelte @@ -7,6 +7,7 @@ import RoomName from "@app/components/RoomName.svelte" import {publishReaction, retractReaction} from "@app/reactions" import ReactionSummary from "@app/components/ReactionSummary.svelte" + import type {FeedContext} from "@app/feeds" import ThunkStatusOrDeleted from "@app/components/ThunkStatusOrDeleted.svelte" import EventActivity from "@app/components/EventActivity.svelte" import EventActions from "@app/components/EventActions.svelte" @@ -18,9 +19,10 @@ event: TrustedEvent showRoom?: boolean showActivity?: boolean + context: FeedContext } - const {url, event, showRoom, showActivity}: Props = $props() + const {url, event, showRoom, showActivity, context}: Props = $props() const article = $derived(reader(Article)(event)) const h = $derived(article.room()) @@ -46,7 +48,13 @@ {/each} - + {#if showActivity} {/if} diff --git a/src/app/components/ArticleItem.svelte b/src/app/components/ArticleItem.svelte index 20c85192..efae3d44 100644 --- a/src/app/components/ArticleItem.svelte +++ b/src/app/components/ArticleItem.svelte @@ -7,15 +7,17 @@ import Content from "@app/components/Content.svelte" import ProfileLink from "@app/components/ProfileLink.svelte" import ArticleActions from "@app/components/ArticleActions.svelte" + import type {FeedContext} from "@app/feeds" import {reader} from "@app/core" import {makeArticlePath} from "@app/routes" type Props = { url: string event: TrustedEvent + context: FeedContext } - const {url, event}: Props = $props() + const {url, event, context}: Props = $props() const article = $derived(reader(Article)(event)) const title = $derived(article.title()) @@ -52,7 +54,7 @@ Written by - + diff --git a/src/app/components/CalendarEventActions.svelte b/src/app/components/CalendarEventActions.svelte index 05537530..3f1c4c12 100644 --- a/src/app/components/CalendarEventActions.svelte +++ b/src/app/components/CalendarEventActions.svelte @@ -8,6 +8,7 @@ import RoomName from "@app/components/RoomName.svelte" import {publishReaction, retractReaction} from "@app/reactions" import ReactionSummary from "@app/components/ReactionSummary.svelte" + import type {FeedContext} from "@app/feeds" import ThunkStatusOrDeleted from "@app/components/ThunkStatusOrDeleted.svelte" import EventActivity from "@app/components/EventActivity.svelte" import EventActions from "@app/components/EventActions.svelte" @@ -21,9 +22,10 @@ event: TrustedEvent showRoom?: boolean showActivity?: boolean + context: FeedContext } - const {url, event, showRoom, showActivity}: Props = $props() + const {url, event, showRoom, showActivity, context}: Props = $props() const h = $derived(tagValue(tagSpec("h"), event.tags)) const path = $derived(makeCalendarPath(url, getAddress(event))) @@ -42,7 +44,13 @@ {/if} - + {#if showActivity} {/if} diff --git a/src/app/components/CalendarEventItem.svelte b/src/app/components/CalendarEventItem.svelte index d52a1e88..255cbf6c 100644 --- a/src/app/components/CalendarEventItem.svelte +++ b/src/app/components/CalendarEventItem.svelte @@ -3,6 +3,7 @@ import {getAddress, tagValue, tagSpec} from "@welshman/util" import Link from "@lib/components/Link.svelte" import CalendarEventActions from "@app/components/CalendarEventActions.svelte" + import type {FeedContext} from "@app/feeds" import CalendarEventHeader from "@app/components/CalendarEventHeader.svelte" import ProfileLink from "@app/components/ProfileLink.svelte" import RoomLink from "@app/components/RoomLink.svelte" @@ -11,9 +12,10 @@ type Props = { url: string event: TrustedEvent + context: FeedContext } - const {url, event}: Props = $props() + const {url, event, context}: Props = $props() const h = $derived(tagValue(tagSpec("h"), event.tags)) @@ -29,6 +31,6 @@ in {/if} - + diff --git a/src/app/components/Chat.svelte b/src/app/components/Chat.svelte index ea5462f7..dc62c52f 100644 --- a/src/app/components/Chat.svelte +++ b/src/app/components/Chat.svelte @@ -1,6 +1,6 @@ {#if $event} {:else}

diff --git a/src/app/components/PollActions.svelte b/src/app/components/PollActions.svelte index 6b258fb2..2dbe41d4 100644 --- a/src/app/components/PollActions.svelte +++ b/src/app/components/PollActions.svelte @@ -5,6 +5,7 @@ import RoomName from "@app/components/RoomName.svelte" import {publishReaction, retractReaction} from "@app/reactions" import ReactionSummary from "@app/components/ReactionSummary.svelte" + import type {FeedContext} from "@app/feeds" import ThunkStatusOrDeleted from "@app/components/ThunkStatusOrDeleted.svelte" import EventActivity from "@app/components/EventActivity.svelte" import EventActions from "@app/components/EventActions.svelte" @@ -15,9 +16,10 @@ event: TrustedEvent showRoom?: boolean showActivity?: boolean + context: FeedContext } - const {url, event, showRoom, showActivity}: Props = $props() + const {url, event, showRoom, showActivity, context}: Props = $props() const h = tagValue(tagSpec("h"), event.tags) const path = makePollPath(url, event.id) @@ -34,7 +36,13 @@ {/if} - + {#if showActivity} {/if} diff --git a/src/app/components/PollItem.svelte b/src/app/components/PollItem.svelte index 91cdcdda..11708aab 100644 --- a/src/app/components/PollItem.svelte +++ b/src/app/components/PollItem.svelte @@ -4,6 +4,7 @@ import Link from "@lib/components/Link.svelte" import NoteContent from "@app/components/NoteContent.svelte" import PollActions from "@app/components/PollActions.svelte" + import type {FeedContext} from "@app/feeds" import RoomLink from "@app/components/RoomLink.svelte" import ProfileLink from "@app/components/ProfileLink.svelte" import {makePollPath} from "@app/routes" @@ -11,9 +12,10 @@ type Props = { url: string event: TrustedEvent + context: FeedContext } - const {url, event}: Props = $props() + const {url, event, context}: Props = $props() const h = tagValue(tagSpec("h"), event.tags) @@ -29,6 +31,6 @@ in {/if} - + diff --git a/src/app/components/ProfileFeed.svelte b/src/app/components/ProfileFeed.svelte index 836052dc..812f5e70 100644 --- a/src/app/components/ProfileFeed.svelte +++ b/src/app/components/ProfileFeed.svelte @@ -1,5 +1,5 @@ {#if $reactions.length > 0 || $zaps.length || $reports.length > 0 || children} diff --git a/src/app/components/RecentItem.svelte b/src/app/components/RecentItem.svelte index 5ec1e9af..6a25599c 100644 --- a/src/app/components/RecentItem.svelte +++ b/src/app/components/RecentItem.svelte @@ -8,30 +8,32 @@ import CalendarEventItem from "@app/components/CalendarEventItem.svelte" import PollItem from "@app/components/PollItem.svelte" import RecentConversation from "@app/components/RecentConversation.svelte" + import type {FeedContext} from "@app/feeds" import type {RecentActivityItem} from "@app/recent" type Props = { url: string item: RecentActivityItem + context: FeedContext } - const {url, item}: Props = $props() + const {url, item, context}: Props = $props() {#if item.type === "message"} {:else if item.event.kind === THREAD} - + {:else if item.event.kind === CLASSIFIED} - + {:else if item.event.kind === LONG_FORM} - + {:else if item.event.kind === ZAP_GOAL} - + {:else if item.event.kind === EVENT_TIME} - + {:else if item.event.kind === POLL} - + {:else} - + {/if} diff --git a/src/app/components/RoomChat.svelte b/src/app/components/RoomChat.svelte index 6cc76b7c..d3bdfd50 100644 --- a/src/app/components/RoomChat.svelte +++ b/src/app/components/RoomChat.svelte @@ -41,7 +41,7 @@ prependParent, } from "@app/rooms" import {userSettingsValues} from "@app/settings" - import {makeFeed} from "@app/feeds" + import {makeFeed, makeFeedContext} from "@app/feeds" import {checked, deferredRoomPath, setChecked} from "@app/notifications" import {makeRoomPath} from "@app/routes" import {pendingShare, type Share} from "@app/share" @@ -54,6 +54,10 @@ const {url, h}: Props = $props() + const context = makeFeedContext({relays: [url]}) + + onDestroy(context.cleanup) + const room = h ? $rooms.forRoom(url, h) : readable(undefined) const addMemberKind = h ? ROOM_ADD_MEMBER : RELAY_ADD_MEMBER const isVoiceRoom = $derived($room && getRoomType($room) === RoomType.Voice) @@ -427,6 +431,7 @@ filters: [ h ? {kinds: [MESSAGE, addMemberKind], "#h": [h]} : {kinds: [MESSAGE, addMemberKind]}, ], + onEvent: context.add, onBackwardExhausted: () => { loadingBackward = false }, @@ -575,6 +580,7 @@ {event} {replyTo} {showPubkey} + {context} canEdit={canEditEvent} onEdit={onEditEvent} /> {/if} diff --git a/src/app/components/RoomItem.svelte b/src/app/components/RoomItem.svelte index cbf72acd..289f60c6 100644 --- a/src/app/components/RoomItem.svelte +++ b/src/app/components/RoomItem.svelte @@ -41,6 +41,7 @@ import {profiles, thunks, user} from "@app/core" import {colors} from "@app/theme" import {ENABLE_ZAPS} from "@app/env" + import type {FeedContext} from "@app/feeds" import {deriveEvent, deriveEventsForUrl} from "@app/repository" import {makeContentPath} from "@app/routes" import {pushModal} from "@app/modal" @@ -50,11 +51,20 @@ event: TrustedEvent replyTo?: (event: TrustedEvent) => void showPubkey?: boolean + context: FeedContext canEdit: (event: TrustedEvent) => boolean onEdit: (event: TrustedEvent) => void } - const {url, event, replyTo = undefined, showPubkey = false, canEdit, onEdit}: Props = $props() + const { + url, + event, + replyTo = undefined, + showPubkey = false, + context, + canEdit, + onEdit, + }: Props = $props() const h = tagValue(tagSpec("h"), event.tags) const today = formatTimestampAsDate(now()) @@ -139,6 +149,7 @@ + import {onDestroy} from "svelte" import History from "@assets/icons/history.svg?dataurl" import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import Icon from "@lib/components/Icon.svelte" import Link from "@lib/components/Link.svelte" import RecentItem from "@app/components/RecentItem.svelte" + import {makeFeedContext} from "@app/feeds" import {deriveRecentActivity} from "@app/recent" import {makeSpacePath} from "@app/routes" @@ -12,9 +14,12 @@ } const {url}: Props = $props() + const context = makeFeedContext({relays: [url]}) const recentActivity = deriveRecentActivity(url) const recentPath = makeSpacePath(url, "recent") + + onDestroy(context.cleanup)

@@ -27,7 +32,7 @@ {:else}
{#each $recentActivity.slice(0, 3) as item (item.event.id)} - + {/each}
{/if} diff --git a/src/app/components/ThreadActions.svelte b/src/app/components/ThreadActions.svelte index 20785e4f..782fd518 100644 --- a/src/app/components/ThreadActions.svelte +++ b/src/app/components/ThreadActions.svelte @@ -5,6 +5,7 @@ import RoomName from "@app/components/RoomName.svelte" import {publishReaction, retractReaction} from "@app/reactions" import ReactionSummary from "@app/components/ReactionSummary.svelte" + import type {FeedContext} from "@app/feeds" import ThunkStatusOrDeleted from "@app/components/ThunkStatusOrDeleted.svelte" import EventActivity from "@app/components/EventActivity.svelte" import EventActions from "@app/components/EventActions.svelte" @@ -15,9 +16,10 @@ event: TrustedEvent showRoom?: boolean showActivity?: boolean + context: FeedContext } - const {url, event, showRoom, showActivity}: Props = $props() + const {url, event, showRoom, showActivity, context}: Props = $props() const h = tagValue(tagSpec("h"), event.tags) const path = makeThreadPath(url, event.id) @@ -33,7 +35,13 @@ {/if} - + {#if showActivity} {/if} diff --git a/src/app/components/ThreadItem.svelte b/src/app/components/ThreadItem.svelte index b0f97de7..5b062efe 100644 --- a/src/app/components/ThreadItem.svelte +++ b/src/app/components/ThreadItem.svelte @@ -6,15 +6,17 @@ import Content from "@app/components/Content.svelte" import ProfileLink from "@app/components/ProfileLink.svelte" import ThreadActions from "@app/components/ThreadActions.svelte" + import type {FeedContext} from "@app/feeds" import RoomLink from "@app/components/RoomLink.svelte" import {makeThreadPath} from "@app/routes" type Props = { url: string event: TrustedEvent + context: FeedContext } - const {url, event}: Props = $props() + const {url, event, context}: Props = $props() const title = tagValue(tagSpec("title"), event.tags) const h = tagValue(tagSpec("h"), event.tags) @@ -44,6 +46,6 @@ in {/if} - +
diff --git a/src/app/components/ThreadPost.svelte b/src/app/components/ThreadPost.svelte index 4a285333..07679fe7 100644 --- a/src/app/components/ThreadPost.svelte +++ b/src/app/components/ThreadPost.svelte @@ -12,6 +12,7 @@ import NoteContent from "@app/components/NoteContent.svelte" import Content from "@app/components/Content.svelte" import CommentActions from "@app/components/CommentActions.svelte" + import type {FeedContext} from "@app/feeds" import ThreadActions from "@app/components/ThreadActions.svelte" import {handles, profiles} from "@app/core" import {makeEventPermalink} from "@app/routes" @@ -23,9 +24,10 @@ event: TrustedEvent threadPubkey: string onReply: (event: TrustedEvent) => void + context: FeedContext } - const {url, event, threadPubkey, onReply}: Props = $props() + const {url, event, threadPubkey, onReply, context}: Props = $props() const profileDisplay = $profiles.display(event.pubkey, [url]).$ const handle = $handles.forPubkey(event.pubkey).$ @@ -90,9 +92,9 @@ Reply {#if isComment} - + {:else} - + {/if} diff --git a/src/app/content.ts b/src/app/content.ts index 259dbf88..5c269dc6 100644 --- a/src/app/content.ts +++ b/src/app/content.ts @@ -36,6 +36,8 @@ export const makeDeleteFilter = (kinds: number[], extra: Filter = {}) => ({ export const REPOST_KINDS = [REPOST, GENERIC_REPOST] +export const REACTION_DISPLAY_KINDS = [REPORT, REACTION, ZAP_RECEIPT] + export const REACTION_KINDS = [REPORT, DELETE, REACTION] if (ENABLE_ZAPS) { diff --git a/src/app/feeds.ts b/src/app/feeds.ts index 53444734..f43f13fe 100644 --- a/src/app/feeds.ts +++ b/src/app/feeds.ts @@ -1,18 +1,179 @@ -import {writable} from "svelte/store" +import {readable, writable} from "svelte/store" +import type {Readable} from "svelte/store" import {batch, between, call, int, now, on, sortBy, uniqBy, MONTH, YEAR} from "@welshman/lib" -import {EVENT_TIME, getAddress, matchFilters, tagSpec, tagValue} from "@welshman/util" +import { + DELETE, + EVENT_TIME, + getAddress, + getReplyFilters, + hexTags, + matchFilters, + tagSpec, + tagValue, + tagValues, +} from "@welshman/util" import type {Filter, TrustedEvent} from "@welshman/util" import {mergeRepositoryUpdates} from "@welshman/net" import type {RepositoryUpdate} from "@welshman/net" import {createScroller} from "@lib/html" import {daysBetween} from "@lib/util" +import {REACTION_DISPLAY_KINDS, REACTION_KINDS} from "@app/content" import {app, network} from "@app/core" import {getEventsForUrl} from "@app/repository" +const noEvents: TrustedEvent[] = [] + +export const makeFeedContext = ({relays}: {relays: string[] | Promise}) => { + const {repository} = app.get() + const controller = new AbortController() + const targets = new Set() + const eventsByTarget = new Map() + const targetsByEventId = new Map() + const subscribersByTarget = new Map void>>() + + const addEvent = (event: TrustedEvent, touched: Set) => { + // An event seen before its target was tracked stays unfiled, so that adding the target + // later can pick it up out of the repository + if (!targetsByEventId.has(event.id)) { + const eventTargets = tagValues(hexTags("e"), event.tags).filter(target => targets.has(target)) + + if (eventTargets.length > 0) { + targetsByEventId.set(event.id, eventTargets) + + for (const target of eventTargets) { + eventsByTarget.set(target, [...(eventsByTarget.get(target) || []), event]) + touched.add(target) + } + } + } + } + + const removeEvent = (id: string, touched: Set) => { + const eventTargets = targetsByEventId.get(id) + + if (eventTargets) { + targetsByEventId.delete(id) + + for (const target of eventTargets) { + const events = eventsByTarget.get(target)!.filter(event => event.id !== id) + + if (events.length > 0) { + eventsByTarget.set(target, events) + } else { + eventsByTarget.delete(target) + } + + touched.add(target) + } + } + } + + const notify = (touched: Set) => { + for (const target of touched) { + for (const subscriber of subscribersByTarget.get(target) || []) { + subscriber(eventsByTarget.get(target) || noEvents) + } + } + } + + const loadContext = batch(100, async (events: TrustedEvent[]) => { + const touched = new Set() + + // What's already local — an earlier page, our own optimistic reactions — never comes + // through the update listener, so file it before asking the network for the rest + for (const event of repository.query( + getReplyFilters(events, {kinds: REACTION_DISPLAY_KINDS}), + )) { + addEvent(event, touched) + } + + notify(touched) + + const urls = await relays + + const context = await network.get().load({ + relays: urls, + signal: controller.signal, + filters: getReplyFilters(events, {kinds: REACTION_KINDS}), + }) + + if (context.length > 0) { + network.get().load({ + relays: urls, + signal: controller.signal, + filters: getReplyFilters(context, {kinds: [DELETE]}), + }) + } + }) + + const unsubscribe = on( + repository, + "update", + batch(150, (updates: RepositoryUpdate[]) => { + const {added, removed} = mergeRepositoryUpdates(updates) + const touched = new Set() + + for (const event of added) { + if (REACTION_DISPLAY_KINDS.includes(event.kind)) { + addEvent(event, touched) + } + } + + for (const id of removed) { + removeEvent(id, touched) + } + + notify(touched) + }), + ) + + // Track an event so its context gets requested with the rest of the batch + const add = (event: TrustedEvent) => { + if (!targets.has(event.id)) { + targets.add(event.id) + loadContext(event) + } + } + + return { + add, + related: (event: TrustedEvent): Readable => { + add(event) + + return readable(eventsByTarget.get(event.id) || noEvents, set => { + let subscribers = subscribersByTarget.get(event.id) + + if (!subscribers) { + subscribers = new Set() + subscribersByTarget.set(event.id, subscribers) + } + + subscribers.add(set) + set(eventsByTarget.get(event.id) || noEvents) + + return () => { + subscribers.delete(set) + + if (subscribers.size === 0) { + subscribersByTarget.delete(event.id) + } + } + }) + }, + cleanup: () => { + controller.abort() + unsubscribe() + }, + } +} + +export type FeedContext = ReturnType + export const makeFeed = ({ relays, filters, element, + onEvent, onBackwardExhausted, onForwardExhausted, at = now(), @@ -20,6 +181,7 @@ export const makeFeed = ({ relays: string[] filters: Filter[] element: HTMLElement + onEvent?: (event: TrustedEvent) => void onBackwardExhausted?: () => void onForwardExhausted?: () => void at?: number @@ -64,6 +226,10 @@ export const makeFeed = ({ if (visible.length > 0) { visible.sort((a, b) => a.created_at - b.created_at) + for (const event of visible) { + onEvent?.(event) + } + events.update($events => { const merged: TrustedEvent[] = [] let i = 0 @@ -223,11 +389,13 @@ export const makeCalendarFeed = ({ relays, filters, element, + onEvent, onExhausted, }: { relays: string[] filters: Filter[] element: HTMLElement + onEvent?: (event: TrustedEvent) => void onExhausted?: () => void }) => { const interval = int(5, MONTH) @@ -260,6 +428,7 @@ export const makeCalendarFeed = ({ for (const event of valid) { seen.add(event.id) + onEvent?.(event) } valid.sort((a, b) => getStart(a) - getStart(b)) diff --git a/src/routes/spaces/[relay]/articles/+page.svelte b/src/routes/spaces/[relay]/articles/+page.svelte index 4a5700e3..008ca911 100644 --- a/src/routes/spaces/[relay]/articles/+page.svelte +++ b/src/routes/spaces/[relay]/articles/+page.svelte @@ -1,5 +1,5 @@ @@ -93,7 +95,7 @@
{#each filtered as event (getAddress(event))}
- +
{/each}

diff --git a/src/routes/spaces/[relay]/articles/[address]/+page.svelte b/src/routes/spaces/[relay]/articles/[address]/+page.svelte index c78886cf..0d2cf656 100644 --- a/src/routes/spaces/[relay]/articles/[address]/+page.svelte +++ b/src/routes/spaces/[relay]/articles/[address]/+page.svelte @@ -1,4 +1,5 @@ @@ -46,10 +51,10 @@

{$article.summary()}

{/if} - +
- + {:else}
{#await sleep(5000)} diff --git a/src/routes/spaces/[relay]/calendar/+page.svelte b/src/routes/spaces/[relay]/calendar/+page.svelte index 1592a932..37eb4e83 100644 --- a/src/routes/spaces/[relay]/calendar/+page.svelte +++ b/src/routes/spaces/[relay]/calendar/+page.svelte @@ -1,5 +1,5 @@ @@ -136,7 +138,7 @@ {#if dateDisplay} {dateDisplay} {/if} - +
{/each} {#if loading} diff --git a/src/routes/spaces/[relay]/calendar/[address]/+page.svelte b/src/routes/spaces/[relay]/calendar/[address]/+page.svelte index bce46c77..4ec7c3ed 100644 --- a/src/routes/spaces/[relay]/calendar/[address]/+page.svelte +++ b/src/routes/spaces/[relay]/calendar/[address]/+page.svelte @@ -1,4 +1,5 @@ @@ -80,7 +82,7 @@ {#each items as event (event.id)}
- +
{/each}

diff --git a/src/routes/spaces/[relay]/classifieds/[address]/+page.svelte b/src/routes/spaces/[relay]/classifieds/[address]/+page.svelte index 1048d2a2..103ab993 100644 --- a/src/routes/spaces/[relay]/classifieds/[address]/+page.svelte +++ b/src/routes/spaces/[relay]/classifieds/[address]/+page.svelte @@ -1,4 +1,5 @@ @@ -80,7 +82,7 @@ {#each items as event (event.id)}

- +
{/each}

diff --git a/src/routes/spaces/[relay]/goals/[id]/+page.svelte b/src/routes/spaces/[relay]/goals/[id]/+page.svelte index 7ae10b5f..a4812bb5 100644 --- a/src/routes/spaces/[relay]/goals/[id]/+page.svelte +++ b/src/routes/spaces/[relay]/goals/[id]/+page.svelte @@ -1,4 +1,5 @@ @@ -80,7 +82,7 @@ {#each items as event (event.id)}

- +
{/each}

diff --git a/src/routes/spaces/[relay]/polls/[id]/+page.svelte b/src/routes/spaces/[relay]/polls/[id]/+page.svelte index 4fda5fab..491c1717 100644 --- a/src/routes/spaces/[relay]/polls/[id]/+page.svelte +++ b/src/routes/spaces/[relay]/polls/[id]/+page.svelte @@ -1,5 +1,5 @@