Keep a profile pinned note out of the feed store so it renders once (#499)
This commit is contained in:
parent
ad480ad4a0
commit
5520b851de
2 changed files with 16 additions and 5 deletions
|
|
@ -465,9 +465,11 @@ test("US-079 read a person's notes", async ({seed, as}) => {
|
|||
makeEvent(NOTE, {content: "Anyone seen the tide charts?", created_at: at(4, HOUR)}),
|
||||
)
|
||||
|
||||
// Older than the feed's first window, so the pin is fetched by id while the feed only
|
||||
// reaches it by paging — the order in which one note arrives down both routes.
|
||||
pinned = space.event(
|
||||
user.alice,
|
||||
makeEvent(NOTE, {content: "PINNED how to read a tide chart", created_at: at(3, HOUR)}),
|
||||
makeEvent(NOTE, {content: "PINNED how to read a tide chart", created_at: at(2, MONTH)}),
|
||||
)
|
||||
|
||||
space.event(
|
||||
|
|
@ -521,6 +523,7 @@ test("US-079 read a person's notes", async ({seed, as}) => {
|
|||
|
||||
// The pin outranks the newer notes; the rest are newest first.
|
||||
await expect(list.first()).toContainText("PINNED")
|
||||
await expect(list.filter({hasText: "PINNED"})).toHaveCount(1)
|
||||
await expect(list.nth(1)).toContainText("NEWEST")
|
||||
await expect(list.nth(2)).toContainText("MIDDLE")
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import {onDestroy, onMount} from "svelte"
|
||||
import {derived, writable} from "svelte/store"
|
||||
import type {Writable} from "svelte/store"
|
||||
import type {Readable} from "svelte/store"
|
||||
import {sortBy, uniqBy, now} from "@welshman/lib"
|
||||
import type {Maybe} from "@welshman/lib"
|
||||
import {NOTE, outbox} from "@welshman/util"
|
||||
|
|
@ -27,6 +27,11 @@
|
|||
|
||||
const pinnedIds = derived($app.use(PinLists).one(pubkey), $pinList => $pinList?.ids() ?? [])
|
||||
|
||||
// Pinned notes are asked for by id instead of by the feed's filters, so they get a store of
|
||||
// their own. A feed dedupes and sorts what it holds as it loads it, and writing to its store
|
||||
// from out here bypasses both.
|
||||
const pinnedEvents = writable<TrustedEvent[]>([])
|
||||
|
||||
$effect(() => {
|
||||
if ($pinnedIds.length > 0) {
|
||||
const controller = new AbortController()
|
||||
|
|
@ -36,7 +41,8 @@
|
|||
relays: $relays,
|
||||
filters: [{ids: $pinnedIds}],
|
||||
signal: controller.signal,
|
||||
onEvent: e => events.update($events => uniqBy(e => e.id, $events.concat(e))),
|
||||
onEvent: event =>
|
||||
pinnedEvents.update($pinned => uniqBy(e => e.id, $pinned.concat(event))),
|
||||
}),
|
||||
)
|
||||
|
||||
|
|
@ -49,12 +55,14 @@
|
|||
|
||||
const exhausted = $derived($older?.status === "exhausted")
|
||||
const loading = $derived(isFeedLoading($older))
|
||||
let events: Writable<TrustedEvent[]> = $state(writable([]))
|
||||
let events: Readable<TrustedEvent[]> = $state(writable([]))
|
||||
|
||||
const feedEvents = $derived(
|
||||
sortBy(
|
||||
e => ($pinnedIds.includes(e.id) ? -(now() + e.created_at) : -e.created_at),
|
||||
$events.filter(e => getReplyTags(e.tags).replies.length === 0),
|
||||
uniqBy(e => e.id, [...$pinnedEvents, ...$events]).filter(
|
||||
e => getReplyTags(e.tags).replies.length === 0,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue