Bump welshman
This commit is contained in:
parent
d974b98c1a
commit
f2b13c6ab9
3 changed files with 75 additions and 36 deletions
20
package.json
20
package.json
|
|
@ -78,16 +78,16 @@
|
|||
"@types/throttle-debounce": "^5.0.2",
|
||||
"@vite-pwa/assets-generator": "^1.0.2",
|
||||
"@vite-pwa/sveltekit": "^1.1.0",
|
||||
"@welshman/app": "^0.9.7",
|
||||
"@welshman/content": "^0.9.7",
|
||||
"@welshman/domain": "^0.9.7",
|
||||
"@welshman/editor": "^0.9.7",
|
||||
"@welshman/feeds": "^0.9.7",
|
||||
"@welshman/lib": "^0.9.7",
|
||||
"@welshman/net": "^0.9.7",
|
||||
"@welshman/signer": "^0.9.7",
|
||||
"@welshman/store": "^0.9.7",
|
||||
"@welshman/util": "^0.9.7",
|
||||
"@welshman/app": "^0.9.8",
|
||||
"@welshman/content": "^0.9.8",
|
||||
"@welshman/domain": "^0.9.8",
|
||||
"@welshman/editor": "^0.9.8",
|
||||
"@welshman/feeds": "^0.9.8",
|
||||
"@welshman/lib": "^0.9.8",
|
||||
"@welshman/net": "^0.9.8",
|
||||
"@welshman/signer": "^0.9.8",
|
||||
"@welshman/store": "^0.9.8",
|
||||
"@welshman/util": "^0.9.8",
|
||||
"cheerio": "^1.2.0",
|
||||
"compressorjs-next": "^1.1.2",
|
||||
"dompurify": "^3.4.13",
|
||||
|
|
|
|||
BIN
pnpm-lock.yaml
BIN
pnpm-lock.yaml
Binary file not shown.
|
|
@ -1,6 +1,6 @@
|
|||
import {derived, get, readable, writable} from "svelte/store"
|
||||
import type {Readable, Writable} from "svelte/store"
|
||||
import {batch, call, int, now, on, sortBy, uniqBy, MONTH, YEAR} from "@welshman/lib"
|
||||
import {batch, call, int, ms, now, on, sleep, sortBy, uniqBy, MONTH, YEAR} from "@welshman/lib"
|
||||
import {
|
||||
COMMENT,
|
||||
DELETE,
|
||||
|
|
@ -324,6 +324,11 @@ export type FeedLoadState =
|
|||
| {status: "searching"}
|
||||
| {status: "exhausted"}
|
||||
|
||||
// One span of a feed's timeline. `complete` is whether the relays actually answered for it: a
|
||||
// request the socket dropped reports nothing found, which is not the same thing as a span with
|
||||
// nothing in it, and the two have to move the window differently.
|
||||
export type FeedSpan = {found: number; complete: boolean; exhausted: boolean}
|
||||
|
||||
// Empty spans to walk per trigger. Enough to cross a gap; not enough to reach the end of the
|
||||
// history on a single request.
|
||||
const SPANS_PER_TRIGGER = 3
|
||||
|
|
@ -334,7 +339,7 @@ const SPANS_PER_TRIGGER = 3
|
|||
export const isFeedLoading = (state: Maybe<FeedLoadState>) =>
|
||||
state?.status === "loading" || state?.status === "searching"
|
||||
|
||||
const makeFeedLoader = (load: () => Promise<{found: number; exhausted: boolean}>) => {
|
||||
const makeFeedLoader = (load: () => Promise<FeedSpan>) => {
|
||||
const state = writable<FeedLoadState>({status: "idle"})
|
||||
|
||||
let running = false
|
||||
|
|
@ -348,17 +353,21 @@ const makeFeedLoader = (load: () => Promise<{found: number; exhausted: boolean}>
|
|||
for (let span = 0; span < SPANS_PER_TRIGGER; span++) {
|
||||
state.set({status: span > 0 ? "searching" : "loading"})
|
||||
|
||||
const {found, exhausted} = await load()
|
||||
const {found, complete, exhausted} = await load()
|
||||
|
||||
if (exhausted) {
|
||||
state.set({status: "exhausted"})
|
||||
return
|
||||
}
|
||||
|
||||
if (found > 0) {
|
||||
state.set({status: "idle"})
|
||||
return
|
||||
// A span nobody answered for hasn't moved the window, so hold here rather than walking
|
||||
// past it, and give the socket a moment before the scroller comes back around
|
||||
if (!complete) {
|
||||
await sleep(ms(3))
|
||||
break
|
||||
}
|
||||
|
||||
if (found > 0) break
|
||||
}
|
||||
|
||||
state.set({status: "idle"})
|
||||
|
|
@ -376,7 +385,7 @@ const makeFeedLoader = (load: () => Promise<{found: number; exhausted: boolean}>
|
|||
// ordinary feed scrolls toward the end of its own content.
|
||||
export const makeScrollLoader = (
|
||||
element: HTMLElement,
|
||||
load: () => Promise<{found: number; exhausted: boolean}>,
|
||||
load: () => Promise<FeedSpan>,
|
||||
options: Partial<ScrollerOpts> = {},
|
||||
) => {
|
||||
const loader = makeFeedLoader(load)
|
||||
|
|
@ -452,41 +461,58 @@ export const makeFeed = ({
|
|||
const unsubscribers = syncFeed({relays, filters, events, seen, insertEvents})
|
||||
|
||||
const loadTimeframe = async (since: number, until: number) => {
|
||||
let complete = false
|
||||
|
||||
const found = await network.get().request({
|
||||
relays,
|
||||
autoClose: true,
|
||||
signal: controller.signal,
|
||||
filters: filters.map(filter => ({...filter, since, until})),
|
||||
onEose: () => {
|
||||
complete = true
|
||||
},
|
||||
})
|
||||
|
||||
// A span that turns up nothing widens the next one, so walking a sparse history doesn't
|
||||
// take dozens of round trips
|
||||
interval = found.length > 0 ? int(MONTH) : Math.round(interval * 1.5)
|
||||
if (complete) {
|
||||
interval = found.length > 0 ? int(MONTH) : Math.round(interval * 1.5)
|
||||
}
|
||||
|
||||
return found.length
|
||||
return {found: found.length, complete}
|
||||
}
|
||||
|
||||
// Ask for the next span in each direction. A span that comes back empty is normal while
|
||||
// walking a sparse history, so the count is reported separately from whether there is any
|
||||
// history left — a caller watching its list for changes would never hear about an empty one.
|
||||
const loadOlder = async () => {
|
||||
if (oldest < now() - int(2, YEAR)) return {found: 0, exhausted: true}
|
||||
// The window only moves once the relays have answered: a request the socket dropped looks
|
||||
// exactly like an empty span, and walking past it would leave a hole nothing goes back for.
|
||||
const loadOlder = async (): Promise<FeedSpan> => {
|
||||
if (oldest < now() - int(2, YEAR)) return {found: 0, complete: true, exhausted: true}
|
||||
|
||||
const until = oldest
|
||||
const since = until - interval
|
||||
const {found, complete} = await loadTimeframe(since, until)
|
||||
|
||||
oldest = until - interval
|
||||
if (complete) {
|
||||
oldest = since
|
||||
}
|
||||
|
||||
return {found: await loadTimeframe(oldest, until), exhausted: false}
|
||||
return {found, complete, exhausted: false}
|
||||
}
|
||||
|
||||
const loadNewer = async () => {
|
||||
if (newest >= now()) return {found: 0, exhausted: true}
|
||||
const loadNewer = async (): Promise<FeedSpan> => {
|
||||
if (newest >= now()) return {found: 0, complete: true, exhausted: true}
|
||||
|
||||
const since = newest
|
||||
const until = Math.min(now(), since + interval)
|
||||
const {found, complete} = await loadTimeframe(since, until)
|
||||
|
||||
newest = Math.min(now(), since + interval)
|
||||
if (complete) {
|
||||
newest = until
|
||||
}
|
||||
|
||||
return {found: await loadTimeframe(since, newest), exhausted: false}
|
||||
return {found, complete, exhausted: false}
|
||||
}
|
||||
|
||||
for (const url of relays) {
|
||||
|
|
@ -584,34 +610,47 @@ export const makeCalendarFeed = ({
|
|||
})
|
||||
|
||||
const loadTimeframe = async (since: number, until: number) => {
|
||||
let complete = false
|
||||
|
||||
const found = await network.get().request({
|
||||
relays,
|
||||
autoClose: true,
|
||||
signal: controller.signal,
|
||||
filters: [{kinds: [EVENT_TIME], "#D": daysBetween(since, until).map(String)}],
|
||||
onEose: () => {
|
||||
complete = true
|
||||
},
|
||||
})
|
||||
|
||||
return found.length
|
||||
return {found: found.length, complete}
|
||||
}
|
||||
|
||||
const loadOlder = async () => {
|
||||
if (oldest < now() - int(2, YEAR)) return {found: 0, exhausted: true}
|
||||
const loadOlder = async (): Promise<FeedSpan> => {
|
||||
if (oldest < now() - int(2, YEAR)) return {found: 0, complete: true, exhausted: true}
|
||||
|
||||
const until = oldest
|
||||
const since = until - interval
|
||||
const {found, complete} = await loadTimeframe(since, until)
|
||||
|
||||
oldest = until - interval
|
||||
if (complete) {
|
||||
oldest = since
|
||||
}
|
||||
|
||||
return {found: await loadTimeframe(oldest, until), exhausted: false}
|
||||
return {found, complete, exhausted: false}
|
||||
}
|
||||
|
||||
const loadNewer = async () => {
|
||||
if (newest > now() + int(2, YEAR)) return {found: 0, exhausted: true}
|
||||
const loadNewer = async (): Promise<FeedSpan> => {
|
||||
if (newest > now() + int(2, YEAR)) return {found: 0, complete: true, exhausted: true}
|
||||
|
||||
const since = newest
|
||||
const until = since + interval
|
||||
const {found, complete} = await loadTimeframe(since, until)
|
||||
|
||||
newest = since + interval
|
||||
if (complete) {
|
||||
newest = until
|
||||
}
|
||||
|
||||
return {found: await loadTimeframe(since, newest), exhausted: false}
|
||||
return {found, complete, exhausted: false}
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
Loading…
Reference in a new issue