Work on feed page

This commit is contained in:
Jon Staab
2026-02-17 17:15:00 -08:00
parent a4e883b09a
commit 4b156ee699
8 changed files with 298 additions and 5 deletions
+39
View File
@@ -0,0 +1,39 @@
<script lang="ts">
import type {Snippet} from "svelte"
import {getAddress} from "@welshman/util"
import History from "@assets/icons/history.svg?dataurl"
import Minus from "@assets/icons/minus.svg?dataurl"
import SecondaryNavSection from "@lib/components/SecondaryNavSection.svelte"
import SecondaryNavHeader from "@lib/components/SecondaryNavHeader.svelte"
import SecondaryNavItem from "@lib/components/SecondaryNavItem.svelte"
import SecondaryNav from "@lib/components/SecondaryNav.svelte"
import Page from "@lib/components/Page.svelte"
import Icon from "@lib/components/Icon.svelte"
import {userFeeds} from "@app/core/state"
type Props = {
children?: Snippet
}
const {children}: Props = $props()
</script>
<SecondaryNav>
<SecondaryNavSection>
<SecondaryNavItem href="/home">
<Icon icon={History} /> Recent Activity
</SecondaryNavItem>
</SecondaryNavSection>
<SecondaryNavSection>
<SecondaryNavHeader>Your Feeds</SecondaryNavHeader>
{#each $userFeeds as feed (feed.event.id)}
<SecondaryNavItem href="/home/feed/{getAddress(feed.event)}">
<Icon icon={Minus} />
{feed.title}
</SecondaryNavItem>
{/each}
</SecondaryNavSection>
</SecondaryNav>
<Page>
{@render children?.()}
</Page>
+2 -3
View File
@@ -13,6 +13,7 @@
getTagValue,
getTagValues,
getIdAndAddress,
getParentIdOrAddr,
} from "@welshman/util"
import type {TrustedEvent} from "@welshman/util"
import {
@@ -129,7 +130,7 @@
makeIntersectionFeed(makeScopeFeed(Scope.Follows), makeKindFeed(NOTE)),
),
onEvent: batch(100, (evts: TrustedEvent[]) => {
events.update($events => [...$events, ...evts])
events.update($events => [...$events, ...evts.filter(e => !getParentIdOrAddr(e))])
}),
onExhausted: () => {
loading = false
@@ -141,7 +142,6 @@
delay: 800,
threshold: 3000,
onScroll: async () => {
console.log("scroll")
limit.update($limit => {
if ($events.length - $limit < 50) {
ctrl.load(50)
@@ -175,7 +175,6 @@
<div class="row-2"></div>
{/snippet}
</PageBar>
<PageContent class="flex flex-col gap-2 p-2 pt-4" bind:element>
{#each $recentActivity as { type, event, url, count } (event.id)}
{#if type === "message"}
@@ -0,0 +1,85 @@
<script lang="ts">
import {onMount} from "svelte"
import {writable} from "svelte/store"
import {batch, call} from "@welshman/lib"
import type {MakeNonOptional} from "@welshman/lib"
import type {TrustedEvent} from "@welshman/util"
import {makeFeedController} from "@welshman/app"
import {page} from "$app/stores"
import {createScroller} from "@lib/html"
import PageBar from "@lib/components/PageBar.svelte"
import PageContent from "@lib/components/PageContent.svelte"
import NoteItem from "@app/components/NoteItem.svelte"
import {deriveFeed} from "@app/core/state"
const {address} = $page.params as MakeNonOptional<typeof $page.params>
const events = writable<TrustedEvent[]>([])
const controller = new AbortController()
const feed = deriveFeed(address)
const limit = writable(0)
let loading = $state(true)
let element: Element | undefined = $state()
onMount(() => {
if ($feed) {
const promise = call(async () => {
const ctrl = makeFeedController({
useWindowing: true,
signal: controller.signal,
feed: $feed.definition,
onEvent: batch(100, (evts: TrustedEvent[]) => {
events.update($events => [...$events, ...evts])
}),
onExhausted: () => {
loading = false
},
})
const scroller = createScroller({
element: element!,
delay: 800,
threshold: 3000,
onScroll: async () => {
limit.update($limit => {
if ($events.length - $limit < 50) {
ctrl.load(50)
}
return $limit + 10
})
},
})
return () => {
scroller.stop()
controller.abort()
}
})
return () => promise.then(call)
}
})
</script>
{#if $feed}
<PageBar>
{#snippet title()}
<h1 class="text-xl">{$feed.title}</h1>
{/snippet}
</PageBar>
<PageContent class="flex flex-col gap-2 p-2 pt-4" bind:element>
{#each $events as event (event.id)}
<NoteItem {event} />
{:else}
{#if loading}
<div class="flex justify-center items-center py-20">
<span class="loading loading-spinner mr-3"></span>
Loading your feed...
</div>
{:else}
<p class="flex flex-col items-center py-20 text-center">No content found!</p>
{/if}
{/each}
</PageContent>
{/if}