mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-30 00:41:12 +00:00
Batch load context on feeds. This makes loading faster, and provides more context
This commit is contained in:
parent
3d095e83ef
commit
3097b9e7e8
12
README.md
12
README.md
@ -22,20 +22,26 @@ If you like Coracle and want to support its development, you can donate sats via
|
|||||||
- [ ] An actual readme
|
- [ ] An actual readme
|
||||||
- [ ] Server discovery and relay publishing - https://github.com/nostr-protocol/nips/pull/32/files
|
- [ ] Server discovery and relay publishing - https://github.com/nostr-protocol/nips/pull/32/files
|
||||||
- [ ] Support invoices https://twitter.com/jb55/status/1604131336247476224
|
- [ ] Support invoices https://twitter.com/jb55/status/1604131336247476224
|
||||||
- [ ] Expand/collapse large threads
|
|
||||||
- [ ] NIP 05
|
- [ ] NIP 05
|
||||||
|
- [ ] Lightning tips
|
||||||
|
- [ ] Direct messages
|
||||||
|
- [ ] Rooms/groups
|
||||||
|
|
||||||
# Bugs
|
# Bugs
|
||||||
|
|
||||||
|
- [ ] Follow fiatjaf's vision of clients being smart and connecting to recommended relays to fetch content
|
||||||
- [ ] Add alerts for replies to posts the user liked
|
- [ ] Add alerts for replies to posts the user liked
|
||||||
- [ ] Stack views so scroll position isn't lost on navigation
|
- [ ] Stack views so scroll position isn't lost on navigation
|
||||||
- [ ] Add notification for slow relays
|
- [ ] Add notification for slow relays, suggest relays based on network
|
||||||
- [ ] Separating events table into notes/reactions/etc would effectively give us a second index on kind.
|
- [ ] Separating events table into notes/reactions/etc would effectively give us a second index on kind.
|
||||||
- [ ] Clicking on a badge in the popover falls through, and might also crash
|
- [ ] Clicking on a badge in the popover falls through, and might also crash
|
||||||
- [ ] Add a slider in settings so users can decide whether to go with fast relays, or wait for everyone to complete their queries. Most relevant for NoteDetail
|
|
||||||
|
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.2.5
|
||||||
|
|
||||||
|
- [x] Batch load context for feeds
|
||||||
|
|
||||||
## 0.2.4
|
## 0.2.4
|
||||||
|
|
||||||
- [x] Fix reactions - livequery is required in order to listen for changes
|
- [x] Fix reactions - livequery is required in order to listen for changes
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import {liveQuery} from 'dexie'
|
import {liveQuery} from 'dexie'
|
||||||
import extractUrls from 'extract-urls'
|
import extractUrls from 'extract-urls'
|
||||||
import {get} from 'svelte/store'
|
import {get} from 'svelte/store'
|
||||||
import {intersection, find, sortBy, propEq, uniqBy, groupBy, concat, without, prop, isNil, identity} from 'ramda'
|
import {uniq, pluck, intersection, sortBy, propEq, uniqBy, groupBy, concat, without, prop, isNil, identity} from 'ramda'
|
||||||
import {ensurePlural, first, createMap, ellipsize} from 'hurdak/lib/hurdak'
|
import {ensurePlural, first, createMap, ellipsize} from 'hurdak/lib/hurdak'
|
||||||
import {escapeHtml} from 'src/util/html'
|
import {escapeHtml} from 'src/util/html'
|
||||||
import {filterTags, getTagValues, findReply, findRoot} from 'src/util/nostr'
|
import {filterTags, getTagValues, findReply, findRoot} from 'src/util/nostr'
|
||||||
@ -221,28 +221,36 @@ const unfollow = async pubkey => {
|
|||||||
// Methods that wil attempt to load from the database and fall back to the network.
|
// Methods that wil attempt to load from the database and fall back to the network.
|
||||||
// This is intended only for bootstrapping listeners
|
// This is intended only for bootstrapping listeners
|
||||||
|
|
||||||
const loadNoteContext = async (note, {loadParent = false} = {}) => {
|
const loadNotesContext = async (notes, {loadParents = false} = {}) => {
|
||||||
const $people = get(people)
|
notes = ensurePlural(notes)
|
||||||
const filter = [{kinds: [1, 5, 7], '#e': [note.id]}]
|
|
||||||
|
|
||||||
// Load the author if needed
|
if (notes.length === 0) {
|
||||||
if (!$people[note.pubkey]) {
|
return
|
||||||
filter.push({kinds: [0], authors: [note.pubkey]})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the note's parent
|
const $people = get(people)
|
||||||
const parentId = findReply(note)
|
const authors = uniq(pluck('pubkey', notes)).filter(k => !$people[k])
|
||||||
if (loadParent && parentId) {
|
const parentIds = loadParents ? uniq(notes.map(findReply).filter(identity)) : []
|
||||||
filter.push({kinds: [1], ids: [parentId]})
|
const filter = [{kinds: [1, 5, 7], '#e': pluck('id', notes)}]
|
||||||
|
|
||||||
|
// Load authors if needed
|
||||||
|
if (authors.length > 0) {
|
||||||
|
filter.push({kinds: [0], authors})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the note parents
|
||||||
|
if (parentIds.length > 0) {
|
||||||
|
filter.push({kinds: [1], ids: parentIds})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the events
|
// Load the events
|
||||||
const events = await pool.loadEvents(filter)
|
const events = await pool.loadEvents(filter)
|
||||||
|
const eventsById = createMap('id', events)
|
||||||
|
const parents = parentIds.map(id => eventsById[id]).filter(identity)
|
||||||
|
|
||||||
// Load the note's context as well
|
// Load the parents' context as well
|
||||||
const parent = find(propEq('id', parentId), events)
|
if (parents.length > 0) {
|
||||||
if (loadParent && parent) {
|
await loadNotesContext(parents)
|
||||||
await loadNoteContext(parent)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,7 +262,7 @@ const getOrLoadNote = async id => {
|
|||||||
const note = await db.events.get(id)
|
const note = await db.events.get(id)
|
||||||
|
|
||||||
if (note) {
|
if (note) {
|
||||||
await loadNoteContext(note, {loadParent: true})
|
await loadNotesContext([note], {loadParent: true})
|
||||||
}
|
}
|
||||||
|
|
||||||
return note
|
return note
|
||||||
@ -296,5 +304,5 @@ export const connections = db.connections
|
|||||||
export default {
|
export default {
|
||||||
db, pool, cmd, lq, filterEvents, getOrLoadNote, filterReplies, findNote,
|
db, pool, cmd, lq, filterEvents, getOrLoadNote, filterReplies, findNote,
|
||||||
annotateChunk, renderNote, login, addRelay, removeRelay,
|
annotateChunk, renderNote, login, addRelay, removeRelay,
|
||||||
follow, unfollow, loadNoteContext,
|
follow, unfollow, loadNotesContext,
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
const scroller = createScroller(async () => {
|
const scroller = createScroller(async () => {
|
||||||
notes = notes.concat(await loadNotes())
|
notes = uniqBy(prop('id'), notes.concat(await loadNotes()))
|
||||||
})
|
})
|
||||||
|
|
||||||
return () => scroller.stop()
|
return () => scroller.stop()
|
||||||
@ -24,25 +24,15 @@
|
|||||||
|
|
||||||
const loadNotes = async () => {
|
const loadNotes = async () => {
|
||||||
const [since, until] = cursor.step()
|
const [since, until] = cursor.step()
|
||||||
|
const filter = {kinds: [1, 7], '#p': [$user.pubkey], since, until}
|
||||||
|
|
||||||
await relay.pool.loadEvents(
|
// Load all our alerts and their context
|
||||||
[{kinds: [1, 7], '#p': [$user.pubkey], since, until}],
|
await relay.loadNotesContext(
|
||||||
e => {
|
await relay.pool.loadEvents(filter),
|
||||||
if (e.kind === 1) {
|
{loadParents: true}
|
||||||
relay.loadNoteContext(e)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
if (e.kind === 7) {
|
|
||||||
const replyId = findReply(e)
|
|
||||||
|
|
||||||
if (replyId) {
|
|
||||||
relay.getOrLoadNote(replyId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
alerts.set({since: now()})
|
alerts.set({since: now()})
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const events = await relay.filterEvents({
|
const events = await relay.filterEvents({
|
||||||
since,
|
since,
|
||||||
@ -80,7 +70,6 @@
|
|||||||
|
|
||||||
// Combine likes of a single note. Remove grandchild likes
|
// Combine likes of a single note. Remove grandchild likes
|
||||||
const likesById = {}
|
const likesById = {}
|
||||||
const alerts = notes.filter(e => e.pubkey !== $user.pubkey)
|
|
||||||
for (const reaction of reactions.filter(e => e.parent?.pubkey === $user.pubkey)) {
|
for (const reaction of reactions.filter(e => e.parent?.pubkey === $user.pubkey)) {
|
||||||
if (!likesById[reaction.parent.id]) {
|
if (!likesById[reaction.parent.id]) {
|
||||||
likesById[reaction.parent.id] = {...reaction.parent, people: []}
|
likesById[reaction.parent.id] = {...reaction.parent, people: []}
|
||||||
@ -91,7 +80,9 @@
|
|||||||
|
|
||||||
return sortBy(
|
return sortBy(
|
||||||
e => -e.created_at,
|
e => -e.created_at,
|
||||||
uniqBy(prop('id'), alerts.concat(Object.values(likesById)))
|
notes
|
||||||
|
.filter(e => e.pubkey !== $user.pubkey)
|
||||||
|
.concat(Object.values(likesById))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
sub = await relay.pool.listenForEvents(
|
sub = await relay.pool.listenForEvents(
|
||||||
'routes/Person',
|
'routes/Person',
|
||||||
[{kinds: [0, 1, 5, 7], authors: [pubkey], since: now()}],
|
[{kinds: [0, 1, 5, 7], authors: [pubkey], since: now()}],
|
||||||
when(propEq('kind', 1), relay.loadNoteContext)
|
when(propEq('kind', 1), relay.loadNotesContext)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
sub = await relay.pool.listenForEvents(
|
sub = await relay.pool.listenForEvents(
|
||||||
'routes/NoteDetail',
|
'routes/NoteDetail',
|
||||||
[{kinds: [1, 5, 7], '#e': [note.id], since: now()}],
|
[{kinds: [1, 5, 7], '#e': [note.id], since: now()}],
|
||||||
when(propEq('kind', 1), relay.loadNoteContext)
|
when(propEq('kind', 1), relay.loadNotesContext)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
sub = await relay.pool.listenForEvents(
|
sub = await relay.pool.listenForEvents(
|
||||||
'views/notes/Global',
|
'views/notes/Global',
|
||||||
[{kinds: [1, 5, 7], since: cursor.since}],
|
[{kinds: [1, 5, 7], since: cursor.since}],
|
||||||
when(propEq('kind', 1), relay.loadNoteContext)
|
when(propEq('kind', 1), relay.loadNotesContext)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -24,13 +24,11 @@
|
|||||||
|
|
||||||
const cursor = new Cursor(timedelta(1, 'minutes'))
|
const cursor = new Cursor(timedelta(1, 'minutes'))
|
||||||
|
|
||||||
const loadNotes = () => {
|
const loadNotes = async () => {
|
||||||
const [since, until] = cursor.step()
|
const [since, until] = cursor.step()
|
||||||
|
const filter = {kinds: [1], since, until}
|
||||||
return relay.pool.loadEvents(
|
const notes = await relay.pool.loadEvents(filter)
|
||||||
[{kinds: [1, 5, 7], since, until}],
|
await relay.loadNotesContext(notes, {loadParents: true})
|
||||||
when(propEq('kind', 1), relay.loadNoteContext)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const queryNotes = () => {
|
const queryNotes = () => {
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
sub = await relay.pool.listenForEvents(
|
sub = await relay.pool.listenForEvents(
|
||||||
'views/notes/Network',
|
'views/notes/Network',
|
||||||
[{kinds: [1, 5, 7], authors: $network, since: cursor.since}],
|
[{kinds: [1, 5, 7], authors: $network, since: cursor.since}],
|
||||||
when(propEq('kind', 1), relay.loadNoteContext)
|
when(propEq('kind', 1), relay.loadNotesContext)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -31,13 +31,11 @@
|
|||||||
|
|
||||||
const cursor = new Cursor(timedelta(10, 'minutes'))
|
const cursor = new Cursor(timedelta(10, 'minutes'))
|
||||||
|
|
||||||
const loadNotes = () => {
|
const loadNotes = async () => {
|
||||||
const [since, until] = cursor.step()
|
const [since, until] = cursor.step()
|
||||||
|
const filter = {kinds: [1, 7], authors: $network, since, until}
|
||||||
return relay.pool.loadEvents(
|
const notes = await relay.pool.loadEvents(filter)
|
||||||
[{kinds: [1, 5, 7], authors: $network, since, until}],
|
await relay.loadNotesContext(notes, {loadParents: true})
|
||||||
when(propEq('kind', 1), relay.loadNoteContext)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const queryNotes = () => {
|
const queryNotes = () => {
|
||||||
|
@ -8,10 +8,14 @@
|
|||||||
|
|
||||||
const cursor = new Cursor(timedelta(1, 'days'))
|
const cursor = new Cursor(timedelta(1, 'days'))
|
||||||
|
|
||||||
const loadNotes = () => {
|
const loadNotes = async () => {
|
||||||
const [since, until] = cursor.step()
|
const [since, until] = cursor.step()
|
||||||
|
const filter = {kinds: [7], authors: [pubkey], since, until}
|
||||||
|
|
||||||
return relay.pool.loadEvents({kinds: [7], authors: [pubkey], since, until})
|
await relay.loadEventsContext(
|
||||||
|
await relay.pool.loadEvents(filter),
|
||||||
|
{loadParents: true}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const queryNotes = () => {
|
const queryNotes = () => {
|
||||||
|
@ -10,13 +10,13 @@
|
|||||||
|
|
||||||
const loadNotes = async () => {
|
const loadNotes = async () => {
|
||||||
const [since, until] = cursor.step()
|
const [since, until] = cursor.step()
|
||||||
|
const authors = getTagValues(person.petnames)
|
||||||
|
const filter = {since, until, kinds: [1], authors}
|
||||||
|
|
||||||
return relay.pool.loadEvents({
|
await relay.loadEventsContext(
|
||||||
since,
|
await relay.pool.loadEvents(filter),
|
||||||
until,
|
{loadParents: true}
|
||||||
kinds: [1],
|
)
|
||||||
authors: getTagValues(person.petnames),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const queryNotes = () => {
|
const queryNotes = () => {
|
||||||
|
@ -7,12 +7,13 @@
|
|||||||
|
|
||||||
const cursor = new Cursor(timedelta(1, 'days'))
|
const cursor = new Cursor(timedelta(1, 'days'))
|
||||||
|
|
||||||
const loadNotes = () => {
|
const loadNotes = async () => {
|
||||||
const [since, until] = cursor.step()
|
const [since, until] = cursor.step()
|
||||||
|
const filter = {kinds: [1], authors: [pubkey], since, until}
|
||||||
|
|
||||||
return relay.pool.loadEvents(
|
await relay.loadNotesContext(
|
||||||
[{kinds: [1], authors: [pubkey], since, until}],
|
await relay.pool.loadEvents(filter),
|
||||||
relay.loadNoteContext
|
{loadParents: true}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user