Compare commits

...

1 Commits

Author SHA1 Message Date
Jon Staab 290585e974 perf: task-fix-list-virtualization changes 2026-04-10 11:36:35 -07:00
5 changed files with 2721 additions and 6 deletions
+2619
View File
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -101,9 +101,9 @@
"onlyBuiltDependencies": [ "onlyBuiltDependencies": [
"sharp", "sharp",
"nostr-signer-capacitor-plugin" "nostr-signer-capacitor-plugin"
], ]
"overrides": { },
"sharp": "0.35.0-rc.0" "overrides": {
} "sharp": "0.35.0-rc.0"
} }
} }
+56
View File
@@ -0,0 +1,56 @@
<script lang="ts">
import type {Snippet} from "svelte"
let {
children,
root,
initiallyVisible = false,
estimatedHeight = 48,
}: {
children: Snippet
root?: HTMLElement
initiallyVisible?: boolean
estimatedHeight?: number
} = $props()
let visible = $state(initiallyVisible)
let height = $state(estimatedHeight)
let el: HTMLElement | undefined = $state()
let hasMeasured = false
$effect(() => {
if (!el) return
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
visible = true
} else {
// Measure actual height before hiding content
if (el) {
const h = el.offsetHeight
if (h > 0) {
height = h
hasMeasured = true
}
}
if (hasMeasured) {
visible = false
}
}
},
{root: root || null, rootMargin: "1000px 0px"},
)
observer.observe(el)
return () => observer.disconnect()
})
</script>
<div bind:this={el}>
{#if visible}
{@render children()}
{:else}
<div style:height="{height}px"></div>
{/if}
</div>
+21 -1
View File
@@ -30,6 +30,7 @@
import SpaceSearch from "@app/components/SpaceSearch.svelte" import SpaceSearch from "@app/components/SpaceSearch.svelte"
import ThunkToast from "@app/components/ThunkToast.svelte" import ThunkToast from "@app/components/ThunkToast.svelte"
import RoomItemAddMember from "@src/app/components/RoomItemAddMember.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 RoomComposeEdit from "@src/app/components/RoomComposeEdit.svelte"
import {canEnforceNip70, prependParent, publishDelete} from "@app/core/commands" import {canEnforceNip70, prependParent, publishDelete} from "@app/core/commands"
import { import {
@@ -105,6 +106,7 @@
const shouldProtect = canEnforceNip70(url) const shouldProtect = canEnforceNip70(url)
const membershipStatus = deriveUserRoomMembershipStatus(url, h) const membershipStatus = deriveUserRoomMembershipStatus(url, h)
const at = $derived(parseInt($page.url.searchParams.get("at")!)) const at = $derived(parseInt($page.url.searchParams.get("at")!))
const shouldVirtualize = $derived(isNaN(at))
const showRoomDetail = () => pushModal(RoomDetail, {url, h}) const showRoomDetail = () => pushModal(RoomDetail, {url, h})
@@ -468,7 +470,7 @@
<Spinner loading={loadingForward}>Looking for messages...</Spinner> <Spinner loading={loadingForward}>Looking for messages...</Spinner>
</p> </p>
{/if} {/if}
{#each elements as { type, id, value, showPubkey, addSpaceBelow } (id)} {#each elements as { type, id, value, showPubkey, addSpaceBelow }, i (id)}
{#if type === "new-messages"} {#if type === "new-messages"}
<div <div
{id} {id}
@@ -480,6 +482,24 @@
</div> </div>
{:else if type === "date"} {:else if type === "date"}
<Divider>{value}</Divider> <Divider>{value}</Divider>
{:else if shouldVirtualize}
<VirtualItem root={element} initiallyVisible={i < 25}>
{@const event = value as TrustedEvent}
{#if event.kind === ROOM_ADD_MEMBER}
<RoomItemAddMember {url} {event} />
{:else}
<div class="cv">
<RoomItem
{url}
{event}
{replyTo}
{showPubkey}
{addSpaceBelow}
canEdit={canEditEvent}
onEdit={onEditEvent} />
</div>
{/if}
</VirtualItem>
{:else} {:else}
{@const event = value as TrustedEvent} {@const event = value as TrustedEvent}
{#if event.kind === ROOM_ADD_MEMBER} {#if event.kind === ROOM_ADD_MEMBER}
+21 -1
View File
@@ -21,6 +21,7 @@
import SpaceSearch from "@app/components/SpaceSearch.svelte" import SpaceSearch from "@app/components/SpaceSearch.svelte"
import RoomItem from "@app/components/RoomItem.svelte" import RoomItem from "@app/components/RoomItem.svelte"
import RoomItemAddMember from "@src/app/components/RoomItemAddMember.svelte" import RoomItemAddMember from "@src/app/components/RoomItemAddMember.svelte"
import VirtualItem from "@lib/components/VirtualItem.svelte"
import RoomCompose from "@app/components/RoomCompose.svelte" import RoomCompose from "@app/components/RoomCompose.svelte"
import RoomComposeEdit from "@src/app/components/RoomComposeEdit.svelte" import RoomComposeEdit from "@src/app/components/RoomComposeEdit.svelte"
@@ -37,6 +38,7 @@
const url = decodeRelay($page.params.relay!) const url = decodeRelay($page.params.relay!)
const shouldProtect = canEnforceNip70(url) const shouldProtect = canEnforceNip70(url)
const at = $derived(parseInt($page.url.searchParams.get("at")!)) const at = $derived(parseInt($page.url.searchParams.get("at")!))
const shouldVirtualize = $derived(isNaN(at))
const replyTo = (event: TrustedEvent) => { const replyTo = (event: TrustedEvent) => {
parent = event parent = event
@@ -305,7 +307,7 @@
<Spinner loading={loadingForward}>Looking for messages...</Spinner> <Spinner loading={loadingForward}>Looking for messages...</Spinner>
</p> </p>
{/if} {/if}
{#each elements as { type, id, value, showPubkey, addSpaceBelow } (id)} {#each elements as { type, id, value, showPubkey, addSpaceBelow }, i (id)}
{#if type === "new-messages"} {#if type === "new-messages"}
<div <div
{id} {id}
@@ -317,6 +319,24 @@
</div> </div>
{:else if type === "date"} {:else if type === "date"}
<Divider>{value}</Divider> <Divider>{value}</Divider>
{:else if shouldVirtualize}
<VirtualItem root={element} initiallyVisible={i < 25}>
{@const event = value as TrustedEvent}
{#if event.kind === RELAY_ADD_MEMBER}
<RoomItemAddMember {url} {event} />
{:else}
<div>
<RoomItem
{url}
{event}
{replyTo}
{showPubkey}
canEdit={canEditEvent}
onEdit={onEditEvent}
{addSpaceBelow} />
</div>
{/if}
</VirtualItem>
{:else} {:else}
{@const event = value as TrustedEvent} {@const event = value as TrustedEvent}
{#if event.kind === RELAY_ADD_MEMBER} {#if event.kind === RELAY_ADD_MEMBER}