From 1d92709c76361b92a298fd6aef6ff578c98fcfe3 Mon Sep 17 00:00:00 2001
From: Jon Staab
Date: Fri, 10 Apr 2026 11:36:35 -0700
Subject: [PATCH] perf: task-fix-list-virtualization changes
---
src/lib/components/VirtualItem.svelte | 56 +++++++++++++++++++++
src/routes/spaces/[relay]/[h]/+page.svelte | 22 +++++++-
src/routes/spaces/[relay]/chat/+page.svelte | 22 +++++++-
3 files changed, 98 insertions(+), 2 deletions(-)
create mode 100644 src/lib/components/VirtualItem.svelte
diff --git a/src/lib/components/VirtualItem.svelte b/src/lib/components/VirtualItem.svelte
new file mode 100644
index 00000000..ee984279
--- /dev/null
+++ b/src/lib/components/VirtualItem.svelte
@@ -0,0 +1,56 @@
+
+
+
+ {#if visible}
+ {@render children()}
+ {:else}
+
+ {/if}
+
diff --git a/src/routes/spaces/[relay]/[h]/+page.svelte b/src/routes/spaces/[relay]/[h]/+page.svelte
index 88bacda8..07bcb254 100644
--- a/src/routes/spaces/[relay]/[h]/+page.svelte
+++ b/src/routes/spaces/[relay]/[h]/+page.svelte
@@ -30,6 +30,7 @@
import SpaceSearch from "@app/components/SpaceSearch.svelte"
import ThunkToast from "@app/components/ThunkToast.svelte"
import RoomItemAddMember from "@src/app/components/RoomItemAddMember.svelte"
+ import VirtualItem from "@lib/components/VirtualItem.svelte"
import RoomComposeEdit from "@src/app/components/RoomComposeEdit.svelte"
import {canEnforceNip70, prependParent, publishDelete} from "@app/core/commands"
import {
@@ -105,6 +106,7 @@
const shouldProtect = canEnforceNip70(url)
const membershipStatus = deriveUserRoomMembershipStatus(url, h)
const at = $derived(parseInt($page.url.searchParams.get("at")!))
+ const shouldVirtualize = $derived(isNaN(at))
const showRoomDetail = () => pushModal(RoomDetail, {url, h})
@@ -472,7 +474,7 @@
Looking for messages...
{/if}
- {#each elements as { type, id, value, showPubkey, addSpaceBelow } (id)}
+ {#each elements as { type, id, value, showPubkey, addSpaceBelow }, i (id)}
{#if type === "new-messages"}
{:else if type === "date"}
{value}
+ {:else if shouldVirtualize}
+
+ {@const event = value as TrustedEvent}
+ {#if event.kind === ROOM_ADD_MEMBER}
+
+ {:else}
+
+
+
+ {/if}
+
{:else}
{@const event = value as TrustedEvent}
{#if event.kind === ROOM_ADD_MEMBER}
diff --git a/src/routes/spaces/[relay]/chat/+page.svelte b/src/routes/spaces/[relay]/chat/+page.svelte
index 08e40d79..f89a94ed 100644
--- a/src/routes/spaces/[relay]/chat/+page.svelte
+++ b/src/routes/spaces/[relay]/chat/+page.svelte
@@ -21,6 +21,7 @@
import SpaceSearch from "@app/components/SpaceSearch.svelte"
import RoomItem from "@app/components/RoomItem.svelte"
import RoomItemAddMember from "@src/app/components/RoomItemAddMember.svelte"
+ import VirtualItem from "@lib/components/VirtualItem.svelte"
import RoomCompose from "@app/components/RoomCompose.svelte"
import RoomComposeEdit from "@src/app/components/RoomComposeEdit.svelte"
@@ -37,6 +38,7 @@
const url = decodeRelay($page.params.relay!)
const shouldProtect = canEnforceNip70(url)
const at = $derived(parseInt($page.url.searchParams.get("at")!))
+ const shouldVirtualize = $derived(isNaN(at))
const replyTo = (event: TrustedEvent) => {
parent = event
@@ -309,7 +311,7 @@
Looking for messages...
{/if}
- {#each elements as { type, id, value, showPubkey, addSpaceBelow } (id)}
+ {#each elements as { type, id, value, showPubkey, addSpaceBelow }, i (id)}
{#if type === "new-messages"}
{:else if type === "date"}
{value}
+ {:else if shouldVirtualize}
+
+ {@const event = value as TrustedEvent}
+ {#if event.kind === RELAY_ADD_MEMBER}
+
+ {:else}
+
+
+
+ {/if}
+
{:else}
{@const event = value as TrustedEvent}
{#if event.kind === RELAY_ADD_MEMBER}