fix some feed loading bugs
This commit is contained in:
parent
10119aaa6d
commit
77ac59008b
11 changed files with 69 additions and 44 deletions
|
|
@ -10,6 +10,7 @@
|
|||
follow,
|
||||
unfollow,
|
||||
tagPubkey,
|
||||
loadRelayList,
|
||||
} from "@welshman/app"
|
||||
import {compressFile} from "@lib/html"
|
||||
import Copy from "@assets/icons/copy.svg?dataurl"
|
||||
|
|
@ -24,6 +25,7 @@
|
|||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import Spinner from "@lib/components/Spinner.svelte"
|
||||
import Popover from "@lib/components/Popover.svelte"
|
||||
import ProfileCircle from "@app/components/ProfileCircle.svelte"
|
||||
import ProfileTrust from "@app/components/ProfileTrust.svelte"
|
||||
|
|
@ -254,7 +256,14 @@
|
|||
<ProfileTrust pubkey={target} {isSelf} />
|
||||
<ProfileSharedSpaces pubkey={target} {isSelf} />
|
||||
</div>
|
||||
<ProfilePageNotes pubkey={target} />
|
||||
{#await loadRelayList(target)}
|
||||
<p class="my-12 flex items-center justify-center gap-2">
|
||||
<Spinner loading />
|
||||
Loading notes...
|
||||
</p>
|
||||
{:then}
|
||||
<ProfilePageNotes pubkey={target} />
|
||||
{/await}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import {onMount} from "svelte"
|
||||
import {derived, writable} from "svelte/store"
|
||||
import type {Writable} from "svelte/store"
|
||||
import {sortBy, now} from "@welshman/lib"
|
||||
import {sortBy, uniqBy, now} from "@welshman/lib"
|
||||
import {NOTE, getReplyTags, getListTags, getEventTagValues} from "@welshman/util"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {derivePinList} from "@welshman/app"
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
relays: Router.get().FromPubkeys([pubkey]).getUrls(),
|
||||
filters: [{ids: $pinnedIds}],
|
||||
signal: controller.signal,
|
||||
onEvent: e => events.update($events => $events.concat(e)),
|
||||
onEvent: e => events.update($events => uniqBy(e => e.id, $events.concat(e))),
|
||||
})
|
||||
|
||||
return () => controller.abort()
|
||||
|
|
@ -50,7 +50,7 @@
|
|||
|
||||
onMount(() => {
|
||||
const feed = makeFeed({
|
||||
url: Router.get().FromPubkeys([pubkey]).getUrls()[0],
|
||||
relays: Router.get().FromPubkeys([pubkey]).getUrls(),
|
||||
element: element!,
|
||||
filters: [{kinds: [NOTE], authors: [pubkey]}],
|
||||
onBackwardExhausted: () => {
|
||||
|
|
@ -75,8 +75,9 @@
|
|||
{/if}
|
||||
{/each}
|
||||
{#if !exhausted}
|
||||
<p class="my-12 flex items-center justify-center">
|
||||
<p class="my-12 flex items-center justify-center gap-2">
|
||||
<Spinner loading />
|
||||
Loading notes...
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import {
|
|||
now,
|
||||
on,
|
||||
sortBy,
|
||||
uniqBy,
|
||||
MONTH,
|
||||
YEAR,
|
||||
} from "@welshman/lib"
|
||||
|
|
@ -105,14 +106,14 @@ export const userFeedFavorites = makeUserData(feedFavoritesByPubkey, loadFeedFav
|
|||
export const loadUserFeedFavorites = makeUserLoader(loadFeedFavorites)
|
||||
|
||||
export const makeFeed = ({
|
||||
url,
|
||||
relays,
|
||||
filters,
|
||||
element,
|
||||
onBackwardExhausted,
|
||||
onForwardExhausted,
|
||||
at = now(),
|
||||
}: {
|
||||
url: string
|
||||
relays: string[]
|
||||
filters: Filter[]
|
||||
element: HTMLElement
|
||||
onBackwardExhausted?: () => void
|
||||
|
|
@ -121,9 +122,15 @@ export const makeFeed = ({
|
|||
}) => {
|
||||
const controller = new AbortController()
|
||||
const events = writable<TrustedEvent[]>([])
|
||||
const seen = new Set<string>()
|
||||
|
||||
let interval = int(MONTH)
|
||||
let buffer = sortEventsDesc(getEventsForUrl(url, filters))
|
||||
let buffer = sortEventsDesc(
|
||||
uniqBy(
|
||||
e => e.id,
|
||||
relays.flatMap(url => Array.from(getEventsForUrl(url, filters))),
|
||||
),
|
||||
)
|
||||
let backwardWindow = [at - interval, at]
|
||||
let forwardWindow = [at, at + interval]
|
||||
|
||||
|
|
@ -142,6 +149,12 @@ export const makeFeed = ({
|
|||
const visible: TrustedEvent[] = []
|
||||
|
||||
for (const event of newEvents) {
|
||||
if (seen.has(event.id)) {
|
||||
continue
|
||||
}
|
||||
|
||||
seen.add(event.id)
|
||||
|
||||
if (between([backwardWindow[0], forwardWindow[1]], event.created_at)) {
|
||||
visible.push(event)
|
||||
} else {
|
||||
|
|
@ -164,6 +177,7 @@ export const makeFeed = ({
|
|||
$events = [...$events, event]
|
||||
}
|
||||
}
|
||||
|
||||
return $events
|
||||
})
|
||||
}
|
||||
|
|
@ -182,7 +196,9 @@ export const makeFeed = ({
|
|||
}
|
||||
|
||||
const matching = added.filter(
|
||||
event => matchFilters(filters, event) && tracker.getRelays(event.id).has(url),
|
||||
event =>
|
||||
matchFilters(filters, event) &&
|
||||
relays.some(url => tracker.getRelays(event.id).has(url)),
|
||||
)
|
||||
|
||||
if (matching.length > 0) {
|
||||
|
|
@ -190,8 +206,8 @@ export const makeFeed = ({
|
|||
}
|
||||
}),
|
||||
),
|
||||
on(tracker, "add", (id: string, trackerUrl: string) => {
|
||||
if (trackerUrl === url) {
|
||||
on(tracker, "add", (id: string, url: string) => {
|
||||
if (relays.includes(url)) {
|
||||
const event = repository.getEvent(id)
|
||||
|
||||
if (event && matchFilters(filters, event)) {
|
||||
|
|
@ -203,7 +219,7 @@ export const makeFeed = ({
|
|||
|
||||
const loadTimeframe = async (since: number, until: number) => {
|
||||
const events = await request({
|
||||
relays: [url],
|
||||
relays,
|
||||
autoClose: true,
|
||||
signal: controller.signal,
|
||||
filters: filters.map(filter => ({...filter, since, until})),
|
||||
|
|
@ -270,18 +286,19 @@ export const makeFeed = ({
|
|||
}
|
||||
|
||||
export const makeCalendarFeed = ({
|
||||
url,
|
||||
relays,
|
||||
filters,
|
||||
element,
|
||||
onExhausted,
|
||||
}: {
|
||||
url: string
|
||||
relays: string[]
|
||||
filters: Filter[]
|
||||
element: HTMLElement
|
||||
onExhausted?: () => void
|
||||
}) => {
|
||||
const interval = int(5, MONTH)
|
||||
const controller = new AbortController()
|
||||
const seen = new Set<string>()
|
||||
|
||||
let exhaustedScrollers = 0
|
||||
let backwardWindow = [now() - interval, now()]
|
||||
|
|
@ -291,15 +308,26 @@ export const makeCalendarFeed = ({
|
|||
|
||||
const getEnd = (event: TrustedEvent) => parseInt(getTagValue("end", event.tags) || "")
|
||||
|
||||
const events = writable(sortBy(getStart, getEventsForUrl(url, filters)))
|
||||
const events = writable(
|
||||
sortBy(
|
||||
getStart,
|
||||
uniqBy(
|
||||
e => e.id,
|
||||
relays.flatMap(url => Array.from(getEventsForUrl(url, filters))),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// Batch-insert calendar events into the store with a single update
|
||||
const insertEvents = (newEvents: TrustedEvent[]) => {
|
||||
const valid = newEvents.filter(e => !isNaN(getStart(e)) && !isNaN(getEnd(e)))
|
||||
const valid = newEvents.filter(e => !isNaN(getStart(e)) && !isNaN(getEnd(e)) && !seen.has(e.id))
|
||||
|
||||
if (valid.length === 0) return
|
||||
|
||||
events.update($events => {
|
||||
for (const event of valid) {
|
||||
seen.add(event.id)
|
||||
|
||||
const start = getStart(event)
|
||||
const address = getAddress(event)
|
||||
|
||||
|
|
@ -320,6 +348,7 @@ export const makeCalendarFeed = ({
|
|||
$events = [...$events.filter(e => getAddress(e) !== address), event]
|
||||
}
|
||||
}
|
||||
|
||||
return $events
|
||||
})
|
||||
}
|
||||
|
|
@ -342,8 +371,8 @@ export const makeCalendarFeed = ({
|
|||
}
|
||||
}),
|
||||
),
|
||||
on(tracker, "add", (id: string, trackerUrl: string) => {
|
||||
if (trackerUrl === url) {
|
||||
on(tracker, "add", (id: string, url: string) => {
|
||||
if (relays.includes(url)) {
|
||||
const event = repository.getEvent(id)
|
||||
|
||||
if (event && matchFilters(filters, event)) {
|
||||
|
|
@ -357,7 +386,7 @@ export const makeCalendarFeed = ({
|
|||
const hashes = daysBetween(since, until).map(String)
|
||||
|
||||
request({
|
||||
relays: [url],
|
||||
relays,
|
||||
autoClose: true,
|
||||
signal: controller.signal,
|
||||
filters: [{kinds: [EVENT_TIME], "#D": hashes}],
|
||||
|
|
|
|||
|
|
@ -19,26 +19,18 @@
|
|||
import {decodePubkey} from "@lib/util"
|
||||
import Page from "@lib/components/Page.svelte"
|
||||
import PageContent from "@lib/components/PageContent.svelte"
|
||||
import Spinner from "@lib/components/Spinner.svelte"
|
||||
import ProfilePage from "@app/components/ProfilePage.svelte"
|
||||
import {loadGroupList} from "@app/groups"
|
||||
|
||||
const {npub} = $page.params as MakeNonOptional<typeof $page.params>
|
||||
|
||||
let pubkey = $state<string | undefined>()
|
||||
let ready = $state(false)
|
||||
const pubkey = decodePubkey(npub)
|
||||
|
||||
onMount(async () => {
|
||||
const decoded = decodePubkey(npub)
|
||||
|
||||
if (!decoded) {
|
||||
goto("/people", {replaceState: true})
|
||||
|
||||
return
|
||||
if (!pubkey) {
|
||||
return goto("/people", {replaceState: true})
|
||||
}
|
||||
|
||||
pubkey = decoded
|
||||
|
||||
try {
|
||||
await loadProfile(pubkey)
|
||||
await loadRelayList(pubkey)
|
||||
|
|
@ -66,8 +58,6 @@
|
|||
relays: Router.get().FromPubkeys([pubkey]).getUrls(),
|
||||
filters,
|
||||
})
|
||||
|
||||
ready = true
|
||||
} catch {
|
||||
goto("/people", {replaceState: true})
|
||||
}
|
||||
|
|
@ -76,12 +66,8 @@
|
|||
|
||||
<Page>
|
||||
<PageContent class="p-0 md:p-4">
|
||||
{#if ready && pubkey}
|
||||
{#if pubkey}
|
||||
<ProfilePage {pubkey} />
|
||||
{:else}
|
||||
<p class="flex items-center justify-center py-20">
|
||||
<Spinner loading />
|
||||
</p>
|
||||
{/if}
|
||||
</PageContent>
|
||||
</Page>
|
||||
|
|
|
|||
|
|
@ -379,7 +379,7 @@
|
|||
cleanup?.()
|
||||
|
||||
const feed = makeFeed({
|
||||
url,
|
||||
relays: [url],
|
||||
at: at || now(),
|
||||
element: element!,
|
||||
filters: [{kinds: [MESSAGE, ROOM_ADD_MEMBER], "#h": [h]}],
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@
|
|||
|
||||
onMount(() => {
|
||||
const feed = makeCalendarFeed({
|
||||
url,
|
||||
relays: [url],
|
||||
element: element!,
|
||||
filters: [{kinds: [EVENT_TIME]}, makeCommentFilter([EVENT_TIME])],
|
||||
onExhausted: () => {
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@
|
|||
cleanup?.()
|
||||
|
||||
const feed = makeFeed({
|
||||
url,
|
||||
relays: [url],
|
||||
at: at || now(),
|
||||
element: element!,
|
||||
filters: [{kinds: [MESSAGE, RELAY_ADD_MEMBER]}],
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
|
||||
onMount(() => {
|
||||
const feed = makeFeed({
|
||||
url,
|
||||
relays: [url],
|
||||
element: element!,
|
||||
filters: [{kinds: [CLASSIFIED]}, makeCommentFilter([CLASSIFIED])],
|
||||
onBackwardExhausted: () => {
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
|
||||
onMount(() => {
|
||||
const feed = makeFeed({
|
||||
url,
|
||||
relays: [url],
|
||||
element: element!,
|
||||
filters: [{kinds: [ZAP_GOAL]}, makeCommentFilter([ZAP_GOAL])],
|
||||
onBackwardExhausted: () => {
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
|
||||
onMount(() => {
|
||||
const feed = makeFeed({
|
||||
url,
|
||||
relays: [url],
|
||||
element: element!,
|
||||
filters: [{kinds: [POLL]}, makeCommentFilter([POLL])],
|
||||
onBackwardExhausted: () => {
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@
|
|||
|
||||
onMount(() => {
|
||||
const feed = makeFeed({
|
||||
url,
|
||||
relays: [url],
|
||||
element: element!,
|
||||
filters: [{kinds: [THREAD]}, makeCommentFilter([THREAD])],
|
||||
onBackwardExhausted: () => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue