diff --git a/src/app/components/ProfilePage.svelte b/src/app/components/ProfilePage.svelte
index e1155854..05afdabc 100644
--- a/src/app/components/ProfilePage.svelte
+++ b/src/app/components/ProfilePage.svelte
@@ -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 @@
-
+ {#await loadRelayList(target)}
+
+
+ Loading notes...
+
+ {:then}
+
+ {/await}
diff --git a/src/app/components/ProfilePageNotes.svelte b/src/app/components/ProfilePageNotes.svelte
index 8664cae8..45106bee 100644
--- a/src/app/components/ProfilePageNotes.svelte
+++ b/src/app/components/ProfilePageNotes.svelte
@@ -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}
-
+
+ Loading notes...
{/if}
diff --git a/src/app/feeds.ts b/src/app/feeds.ts
index 1f57f6eb..f42adc59 100644
--- a/src/app/feeds.ts
+++ b/src/app/feeds.ts
@@ -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([])
+ const seen = new Set()
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()
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}],
diff --git a/src/routes/people/[npub]/+page.svelte b/src/routes/people/[npub]/+page.svelte
index 8377e6a8..ab90aaa2 100644
--- a/src/routes/people/[npub]/+page.svelte
+++ b/src/routes/people/[npub]/+page.svelte
@@ -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
- let pubkey = $state()
- 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 @@
- {#if ready && pubkey}
+ {#if pubkey}
- {:else}
-
-
-
{/if}
diff --git a/src/routes/spaces/[relay]/[h]/+page.svelte b/src/routes/spaces/[relay]/[h]/+page.svelte
index 1877ad97..e2cb7c06 100644
--- a/src/routes/spaces/[relay]/[h]/+page.svelte
+++ b/src/routes/spaces/[relay]/[h]/+page.svelte
@@ -379,7 +379,7 @@
cleanup?.()
const feed = makeFeed({
- url,
+ relays: [url],
at: at || now(),
element: element!,
filters: [{kinds: [MESSAGE, ROOM_ADD_MEMBER], "#h": [h]}],
diff --git a/src/routes/spaces/[relay]/calendar/+page.svelte b/src/routes/spaces/[relay]/calendar/+page.svelte
index 0b04a925..894abbaa 100644
--- a/src/routes/spaces/[relay]/calendar/+page.svelte
+++ b/src/routes/spaces/[relay]/calendar/+page.svelte
@@ -95,7 +95,7 @@
onMount(() => {
const feed = makeCalendarFeed({
- url,
+ relays: [url],
element: element!,
filters: [{kinds: [EVENT_TIME]}, makeCommentFilter([EVENT_TIME])],
onExhausted: () => {
diff --git a/src/routes/spaces/[relay]/chat/+page.svelte b/src/routes/spaces/[relay]/chat/+page.svelte
index 4b796944..a86d9e12 100644
--- a/src/routes/spaces/[relay]/chat/+page.svelte
+++ b/src/routes/spaces/[relay]/chat/+page.svelte
@@ -260,7 +260,7 @@
cleanup?.()
const feed = makeFeed({
- url,
+ relays: [url],
at: at || now(),
element: element!,
filters: [{kinds: [MESSAGE, RELAY_ADD_MEMBER]}],
diff --git a/src/routes/spaces/[relay]/classifieds/+page.svelte b/src/routes/spaces/[relay]/classifieds/+page.svelte
index 7a6a8373..6292be45 100644
--- a/src/routes/spaces/[relay]/classifieds/+page.svelte
+++ b/src/routes/spaces/[relay]/classifieds/+page.svelte
@@ -46,7 +46,7 @@
onMount(() => {
const feed = makeFeed({
- url,
+ relays: [url],
element: element!,
filters: [{kinds: [CLASSIFIED]}, makeCommentFilter([CLASSIFIED])],
onBackwardExhausted: () => {
diff --git a/src/routes/spaces/[relay]/goals/+page.svelte b/src/routes/spaces/[relay]/goals/+page.svelte
index 9a1c5523..063823bf 100644
--- a/src/routes/spaces/[relay]/goals/+page.svelte
+++ b/src/routes/spaces/[relay]/goals/+page.svelte
@@ -46,7 +46,7 @@
onMount(() => {
const feed = makeFeed({
- url,
+ relays: [url],
element: element!,
filters: [{kinds: [ZAP_GOAL]}, makeCommentFilter([ZAP_GOAL])],
onBackwardExhausted: () => {
diff --git a/src/routes/spaces/[relay]/polls/+page.svelte b/src/routes/spaces/[relay]/polls/+page.svelte
index bcf2350b..13fffe84 100644
--- a/src/routes/spaces/[relay]/polls/+page.svelte
+++ b/src/routes/spaces/[relay]/polls/+page.svelte
@@ -46,7 +46,7 @@
onMount(() => {
const feed = makeFeed({
- url,
+ relays: [url],
element: element!,
filters: [{kinds: [POLL]}, makeCommentFilter([POLL])],
onBackwardExhausted: () => {
diff --git a/src/routes/spaces/[relay]/threads/+page.svelte b/src/routes/spaces/[relay]/threads/+page.svelte
index fdfb4b05..026c2f12 100644
--- a/src/routes/spaces/[relay]/threads/+page.svelte
+++ b/src/routes/spaces/[relay]/threads/+page.svelte
@@ -52,7 +52,7 @@
onMount(() => {
const feed = makeFeed({
- url,
+ relays: [url],
element: element!,
filters: [{kinds: [THREAD]}, makeCommentFilter([THREAD])],
onBackwardExhausted: () => {