mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-19 19:46:42 +00:00
Re-work streamContext
This commit is contained in:
parent
6722131c8f
commit
ab1c2cb210
@ -129,35 +129,74 @@ const loadParents = (notes, opts = {}) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const streamContext = ({notes, onChunk, depth = 0}) =>
|
const streamContext = ({notes, onChunk, maxDepth = 2}) => {
|
||||||
// Some relays reject very large filters, send multiple subscriptions
|
const subs = []
|
||||||
Promise.all(
|
const seen = new Set()
|
||||||
chunk(256, notes).map(async events => {
|
const relays = sampleRelays(aggregateScores(notes.map(getRelaysForEventChildren)))
|
||||||
// Instead of recurring to depth, trampoline so we can batch requests
|
|
||||||
while (events.length > 0 && depth > 0) {
|
|
||||||
const chunk = events.splice(0)
|
|
||||||
const authors = getStalePubkeys(pluck("pubkey", chunk))
|
|
||||||
const filter = [{kinds: [1, 7, 9735], "#e": pluck("id", chunk)}] as Array<object>
|
|
||||||
const relays = sampleRelays(aggregateScores(chunk.map(getRelaysForEventChildren)))
|
|
||||||
|
|
||||||
// Load authors and reactions in one subscription
|
const loadChunk = (events, depth) => {
|
||||||
if (authors.length > 0) {
|
// Remove anything from the chunk we've already seen
|
||||||
filter.push({kinds: personKinds, authors})
|
events = events.filter(e => e.kind === 1 && !seen.has(e.id))
|
||||||
}
|
|
||||||
|
|
||||||
depth -= 1
|
// If we have no new information, no need to re-subscribe
|
||||||
|
if (events.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const promise = load({relays, filter, onChunk})
|
// Add our new events to the list of stuff we've seen
|
||||||
|
events.forEach(e => seen.add(e.id))
|
||||||
|
|
||||||
// Don't await the promise when we're on the last level, since we won't be
|
// Unsubscribe our current listeners since we're about to replace them
|
||||||
// displaying those replies, and we await `load` before showing children
|
subs.map(sub => sub.then(s => s.unsub()))
|
||||||
// to reduce reflow
|
|
||||||
if (depth > 0) {
|
// Add a subscription for each chunk to listen for new likes/replies/zaps
|
||||||
events = await promise
|
chunk(256, Array.from(seen)).forEach(ids => {
|
||||||
}
|
subs.push(
|
||||||
}
|
listen({
|
||||||
|
relays,
|
||||||
|
filter: [{kinds: [1, 7, 9735], "#e": ids, since: now()}],
|
||||||
|
onChunk: newEvents => {
|
||||||
|
onChunk(newEvents)
|
||||||
|
|
||||||
|
if (depth < maxDepth) {
|
||||||
|
loadChunk(newEvents, depth + 1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
})
|
})
|
||||||
)
|
|
||||||
|
const newIds = pluck("id", events)
|
||||||
|
const pubkeys = pluck("pubkey", events)
|
||||||
|
|
||||||
|
// Load any people we should know about
|
||||||
|
loadPeople(pubkeys)
|
||||||
|
|
||||||
|
// Load data prior to now for our new ids
|
||||||
|
chunk(256, newIds).forEach(ids => {
|
||||||
|
load({
|
||||||
|
relays,
|
||||||
|
filter: [{kinds: [1, 7, 9735], "#e": ids}],
|
||||||
|
onChunk: newEvents => {
|
||||||
|
onChunk(newEvents)
|
||||||
|
|
||||||
|
if (depth < maxDepth) {
|
||||||
|
loadChunk(newEvents, depth + 1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kick things off by loading our first chunk
|
||||||
|
loadChunk(notes, 1)
|
||||||
|
|
||||||
|
return {
|
||||||
|
unsub: () => {
|
||||||
|
subs.map(sub => sub.then(s => s.unsub()))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const applyContext = (notes, context) => {
|
const applyContext = (notes, context) => {
|
||||||
context = context.map(assoc("isContext", true))
|
context = context.map(assoc("isContext", true))
|
||||||
|
@ -66,7 +66,7 @@
|
|||||||
|
|
||||||
// Stream in additional data and merge it in
|
// Stream in additional data and merge it in
|
||||||
network.streamContext({
|
network.streamContext({
|
||||||
depth: 2,
|
maxDepth: 2,
|
||||||
notes: combined.filter(propEq("kind", 1)),
|
notes: combined.filter(propEq("kind", 1)),
|
||||||
onChunk: context => {
|
onChunk: context => {
|
||||||
context = user.applyMutes(context)
|
context = user.applyMutes(context)
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
<script>
|
<script>
|
||||||
import {onMount} from "svelte"
|
import {onMount, onDestroy} from "svelte"
|
||||||
import {pluck, propEq} from "ramda"
|
import {nip19} from "nostr-tools"
|
||||||
import {fly} from "svelte/transition"
|
import {fly} from "svelte/transition"
|
||||||
import {first} from "hurdak/lib/hurdak"
|
import {first} from "hurdak/lib/hurdak"
|
||||||
|
import {log} from "src/util/logger"
|
||||||
import {asDisplayEvent} from "src/util/nostr"
|
import {asDisplayEvent} from "src/util/nostr"
|
||||||
import Content from "src/partials/Content.svelte"
|
import Content from "src/partials/Content.svelte"
|
||||||
import Spinner from "src/partials/Spinner.svelte"
|
import Spinner from "src/partials/Spinner.svelte"
|
||||||
import Note from "src/views/notes/Note.svelte"
|
import Note from "src/views/notes/Note.svelte"
|
||||||
|
import user from "src/agent/user"
|
||||||
import network from "src/agent/network"
|
import network from "src/agent/network"
|
||||||
import {sampleRelays} from "src/agent/relays"
|
import {sampleRelays} from "src/agent/relays"
|
||||||
|
|
||||||
@ -14,58 +16,41 @@
|
|||||||
export let relays = []
|
export let relays = []
|
||||||
export let invertColors = false
|
export let invertColors = false
|
||||||
|
|
||||||
let found = false
|
let sub = null
|
||||||
let loading = true
|
let loading = true
|
||||||
let seen = new Set()
|
|
||||||
|
|
||||||
onMount(() => {
|
onMount(async () => {
|
||||||
const sub = network.listen({
|
if (!note.pubkey) {
|
||||||
relays: sampleRelays(relays),
|
await network.load({
|
||||||
filter: [
|
relays: sampleRelays(relays),
|
||||||
{kinds: [1], ids: [note.id]},
|
filter: {kinds: [1], ids: [note.id]},
|
||||||
{kinds: [1, 7, 9735], "#e": [note.id]},
|
onChunk: events => {
|
||||||
],
|
note = first(events)
|
||||||
onChunk: chunk => {
|
},
|
||||||
const children = chunk.filter(propEq("kind", 1))
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Recursively bring in context for children, since reactions etc don't
|
if (note) {
|
||||||
// contain the full chain of ancestors
|
log("NoteDetail", nip19.noteEncode(note.id), note)
|
||||||
network.streamContext({
|
|
||||||
depth: 5,
|
|
||||||
notes: children.filter(e => !seen.has(e.id)),
|
|
||||||
onChunk: childChunk => {
|
|
||||||
note = first(network.applyContext([note], childChunk))
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
// Keep track of the children we've seen, update latest version of our note
|
sub = network.streamContext({
|
||||||
children.forEach(event => {
|
maxDepth: 6,
|
||||||
if (event.id === note.id) {
|
notes: [note],
|
||||||
found = true
|
onChunk: context => {
|
||||||
loading = false
|
note = first(network.applyContext([note], user.applyMutes(context)))
|
||||||
note = {...note, ...event}
|
},
|
||||||
}
|
})
|
||||||
|
}
|
||||||
|
|
||||||
seen.add(event.id)
|
loading = false
|
||||||
})
|
})
|
||||||
|
|
||||||
// Load authors
|
onDestroy(() => {
|
||||||
network.loadPeople(pluck("pubkey", children))
|
sub?.unsub()
|
||||||
|
|
||||||
// Apply context
|
|
||||||
note = first(network.applyContext([note], chunk))
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
loading = false
|
|
||||||
}, 3000)
|
|
||||||
|
|
||||||
return () => sub.then(s => s.unsub())
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if !loading && !found}
|
{#if !loading && !note.content}
|
||||||
<div in:fly={{y: 20}}>
|
<div in:fly={{y: 20}}>
|
||||||
<Content size="lg" class="text-center">Sorry, we weren't able to find this note.</Content>
|
<Content size="lg" class="text-center">Sorry, we weren't able to find this note.</Content>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user