Render a feed as one unbroken stretch back from its anchor
This commit is contained in:
parent
e47957b4c2
commit
d905c9dc1b
3 changed files with 69 additions and 13 deletions
|
|
@ -1715,6 +1715,9 @@ Acceptance:
|
||||||
drawn underneath it, and never appears as an item of its own.
|
drawn underneath it, and never appears as an item of its own.
|
||||||
- Every note carries its reply count, including the ones with no replies.
|
- Every note carries its reply count, including the ones with no replies.
|
||||||
- Scrolling to the end of the feed loads more rather than asking her to.
|
- Scrolling to the end of the feed loads more rather than asking her to.
|
||||||
|
- The feed is one unbroken stretch back from now. A relay that answers a page
|
||||||
|
from further back than the rest have been asked about waits for the feed to
|
||||||
|
reach it, so nothing lands below the end of the list.
|
||||||
- The section fills from the relays that answer. One that takes the connection
|
- The section fills from the relays that answer. One that takes the connection
|
||||||
and then says nothing does not hold it empty.
|
and then says nothing does not hold it empty.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -507,6 +507,61 @@ test("US-117 read a follow who is in none of your spaces", async ({seed, as}) =>
|
||||||
expect(fromSpace).toEqual([])
|
expect(fromSpace).toEqual([])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("US-117 read a network feed whose relays answer from different depths", async ({seed, as}) => {
|
||||||
|
// What each relay is asked for one page at a time. A relay that fills its page has only covered
|
||||||
|
// as far back as the page reaches, so a busy one is what decides how far the feed has got.
|
||||||
|
const pageSize = 100
|
||||||
|
const recent = "the harbourmaster moved the moorings again"
|
||||||
|
const deep = "the old crane was scrapped in the spring"
|
||||||
|
|
||||||
|
await seed(({relay, open, user, at}) => {
|
||||||
|
const space = relay("space")
|
||||||
|
const indexer = open("indexer")
|
||||||
|
const outbox = open("outbox")
|
||||||
|
|
||||||
|
space.room("general", {name: "General"})
|
||||||
|
space.join(user.alice, "general")
|
||||||
|
|
||||||
|
indexer.relayList(user.alice, {
|
||||||
|
read: [space.url, indexer.url],
|
||||||
|
write: [space.url, indexer.url, outbox.url],
|
||||||
|
})
|
||||||
|
indexer.follows(user.alice, [user.bob])
|
||||||
|
|
||||||
|
// Bob writes to both, so the feed asks both. His busy relay holds more than one page of the
|
||||||
|
// last couple of hours; his quiet one holds a single note from a week ago.
|
||||||
|
indexer.relayList(user.bob, {read: [outbox.url], write: [outbox.url, indexer.url]})
|
||||||
|
outbox.profile(user.bob, {name: "Bob Barker"})
|
||||||
|
|
||||||
|
outbox.note(user.bob, recent, at(1, MINUTE))
|
||||||
|
|
||||||
|
// More than one page, so the page comes back full however the relay rounds it
|
||||||
|
for (let minute = 2; minute <= pageSize + 10; minute++) {
|
||||||
|
outbox.note(user.bob, `mooring report ${minute}`, at(minute, MINUTE))
|
||||||
|
}
|
||||||
|
|
||||||
|
indexer.note(user.bob, deep, at(7, DAY))
|
||||||
|
})
|
||||||
|
|
||||||
|
const page = await as(users.alice, "/home")
|
||||||
|
|
||||||
|
const network = page
|
||||||
|
.locator("section")
|
||||||
|
.filter({has: page.getByRole("heading", {name: "Network"})})
|
||||||
|
|
||||||
|
await expect(network.getByText(recent)).toBeVisible()
|
||||||
|
|
||||||
|
// The quiet relay answered from a week back, which is days below where the busy one has been
|
||||||
|
// asked about. Drawing it would put a note under the end of the list with the whole week
|
||||||
|
// between still missing.
|
||||||
|
await expect(network.getByText(deep)).toHaveCount(0)
|
||||||
|
|
||||||
|
// It is held rather than dropped, so the feed hands it over once it has paged back that far.
|
||||||
|
await network.locator(".card").last().scrollIntoViewIfNeeded()
|
||||||
|
|
||||||
|
await expect(network.getByText(deep)).toBeVisible()
|
||||||
|
})
|
||||||
|
|
||||||
test("US-117 read the network feed when one relay never answers", async ({seed, as}) => {
|
test("US-117 read the network feed when one relay never answers", async ({seed, as}) => {
|
||||||
// Nothing serves this url, and nothing needs to: the fault is a relay that takes the socket and
|
// Nothing serves this url, and nothing needs to: the fault is a relay that takes the socket and
|
||||||
// then says nothing, which is all the spec asks of it.
|
// then says nothing, which is all the spec asks of it.
|
||||||
|
|
|
||||||
|
|
@ -530,8 +530,8 @@ export const makeFeed = ({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// What arrives from elsewhere in the app, which is only rendered as far back as the feed has
|
// The one door into the feed, so that what it renders is one unbroken stretch back from the
|
||||||
// got to on its own
|
// anchor: anything older than the feed has reached waits there until the window gets to it.
|
||||||
const addEvents = (newEvents: TrustedEvent[]) => {
|
const addEvents = (newEvents: TrustedEvent[]) => {
|
||||||
const ready: TrustedEvent[] = []
|
const ready: TrustedEvent[] = []
|
||||||
|
|
||||||
|
|
@ -644,7 +644,11 @@ export const makeFeed = ({
|
||||||
oldest = edge === undefined ? since : Math.min(edge, until - 1)
|
oldest = edge === undefined ? since : Math.min(edge, until - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
insertEvents(found)
|
// A span reaches further back than it covers. A relay holding few of these authors answers
|
||||||
|
// a page from days deeper than a busy one does, and rendering that stretch leaves a list
|
||||||
|
// whose bottom is a scatter the window then fills in above — so it waits for the window
|
||||||
|
// like anything else arriving early.
|
||||||
|
addEvents(found)
|
||||||
reach(oldest)
|
reach(oldest)
|
||||||
|
|
||||||
return {found: found.length, complete, exhausted: false}
|
return {found: found.length, complete, exhausted: false}
|
||||||
|
|
@ -666,20 +670,14 @@ export const makeFeed = ({
|
||||||
newest = until
|
newest = until
|
||||||
}
|
}
|
||||||
|
|
||||||
insertEvents(found)
|
addEvents(found)
|
||||||
|
|
||||||
return {found: found.length, complete, exhausted: false}
|
return {found: found.length, complete, exhausted: false}
|
||||||
}
|
}
|
||||||
|
|
||||||
// What the repository already holds for these relays is in hand and goes in as one insert,
|
// What the repository already holds is a scatter rather than a stretch — an earlier visit's
|
||||||
// which takes the window back with it rather than leaving the rest of that stretch behind
|
// pages, a reply pulled in as context from weeks back — so it waits for the window too.
|
||||||
const cached = relays.flatMap(url => Array.from(getEventsForUrl(url, filters)))
|
addEvents(relays.flatMap(url => Array.from(getEventsForUrl(url, filters))))
|
||||||
|
|
||||||
for (const event of cached) {
|
|
||||||
reached = Math.min(reached, event.created_at)
|
|
||||||
}
|
|
||||||
|
|
||||||
insertEvents(cached)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
events,
|
events,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue