Suspend subscriptions while modal is open
This commit is contained in:
parent
0e8d0815c4
commit
98313091d1
|
@ -9,8 +9,7 @@
|
|||
export let note
|
||||
|
||||
onMount(() => {
|
||||
return findNotes(
|
||||
channels.watcher,
|
||||
const start = findNotes(
|
||||
[{ids: [note.id]},
|
||||
{'#e': [note.id]},
|
||||
// We can't target reaction deletes by e tag, so get them
|
||||
|
@ -20,6 +19,8 @@
|
|||
note = find(propEq('id', note.id), $notes) || note
|
||||
}
|
||||
)
|
||||
|
||||
return start()
|
||||
})
|
||||
</script>
|
||||
|
||||
|
|
|
@ -5,41 +5,22 @@
|
|||
import Anchor from "src/partials/Anchor.svelte"
|
||||
import Note from "src/partials/Note.svelte"
|
||||
import {channels, relays} from "src/state/nostr"
|
||||
import {findNotes, modal} from "src/state/app"
|
||||
import {findNotesAndWatchModal, modal} from "src/state/app"
|
||||
|
||||
let stop
|
||||
let notes
|
||||
|
||||
const createNote = () => {
|
||||
navigate("/notes/new")
|
||||
}
|
||||
|
||||
const start = () => {
|
||||
stop = findNotes(channels.watcher, {
|
||||
since: now() - timedelta(1, 'days'),
|
||||
onMount(() => {
|
||||
return findNotesAndWatchModal({
|
||||
limit: 100,
|
||||
}, $notes => {
|
||||
if ($notes.length) {
|
||||
notes = $notes
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
onMount(() => {
|
||||
const unsub = modal.subscribe($modal => {
|
||||
console.log('modal', $modal)
|
||||
if ($modal) {
|
||||
stop && stop()
|
||||
} else {
|
||||
setTimeout(start, 600)
|
||||
}
|
||||
})
|
||||
|
||||
return () => {
|
||||
stop()
|
||||
unsub()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import Note from "src/partials/Note.svelte"
|
||||
import {channels} from 'src/state/nostr'
|
||||
import {user as currentUser} from 'src/state/user'
|
||||
import {accounts, findNotes} from "src/state/app"
|
||||
import {accounts, findNotesAndWatchModal, modal} from "src/state/app"
|
||||
|
||||
export let pubkey
|
||||
|
||||
|
@ -15,13 +15,14 @@
|
|||
|
||||
$: user = $accounts[pubkey]
|
||||
|
||||
onMount(async () => {
|
||||
return findNotes(channels.watcher, {
|
||||
onMount(() => {
|
||||
return findNotesAndWatchModal({
|
||||
authors: [pubkey],
|
||||
since: now() - timedelta(1, 'days'),
|
||||
limit: 100,
|
||||
}, $notes => {
|
||||
notes = $notes
|
||||
if ($notes.length) {
|
||||
notes = $notes
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
|
141
src/state/app.js
141
src/state/app.js
|
@ -1,7 +1,7 @@
|
|||
import {prop, uniq, pluck, sortBy, uniqBy, find, last, groupBy} from 'ramda'
|
||||
import {prop, uniq, sortBy, uniqBy, find, last, groupBy} from 'ramda'
|
||||
import {debounce} from 'throttle-debounce'
|
||||
import {writable, derived, get} from 'svelte/store'
|
||||
import {switcherFn, ensurePlural} from 'hurdak/lib/hurdak'
|
||||
import {switcherFn, noop, ensurePlural} from 'hurdak/lib/hurdak'
|
||||
import {getLocalJson, setLocalJson, now, timedelta} from "src/util/misc"
|
||||
import {user} from 'src/state/user'
|
||||
import {channels} from 'src/state/nostr'
|
||||
|
@ -56,72 +56,105 @@ export const ensureAccounts = async pubkeys => {
|
|||
})
|
||||
}
|
||||
|
||||
export const findNotes = (channel, queries, cb) => {
|
||||
const notes = writable([])
|
||||
const reactions = writable([])
|
||||
export const findNotes = (filters, cb) => {
|
||||
const start = () => {
|
||||
const notes = writable([])
|
||||
const reactions = writable([])
|
||||
|
||||
let pubkeys = []
|
||||
let pubkeys = []
|
||||
|
||||
const refreshAccounts = debounce(300, () => {
|
||||
ensureAccounts(uniq(pubkeys))
|
||||
const refreshAccounts = debounce(300, () => {
|
||||
ensureAccounts(uniq(pubkeys))
|
||||
|
||||
pubkeys = []
|
||||
})
|
||||
pubkeys = []
|
||||
})
|
||||
|
||||
const closeRequest = channel.sub({
|
||||
filter: ensurePlural(queries).map(q => ({kinds: [1, 5, 7], ...q})),
|
||||
cb: e => {
|
||||
// Chunk requests to load accounts
|
||||
pubkeys.push(e.pubkey)
|
||||
refreshAccounts()
|
||||
const closeRequest = channels.watcher.sub({
|
||||
filter: ensurePlural(filters).map(q => ({kinds: [1, 5, 7], ...q})),
|
||||
cb: e => {
|
||||
// Chunk requests to load accounts
|
||||
pubkeys.push(e.pubkey)
|
||||
refreshAccounts()
|
||||
|
||||
switcherFn(e.kind, {
|
||||
1: () => {
|
||||
notes.update($xs => uniqBy(prop('id'), $xs.concat(e)))
|
||||
},
|
||||
5: () => {
|
||||
const ids = e.tags.map(t => t[1])
|
||||
switcherFn(e.kind, {
|
||||
1: () => {
|
||||
notes.update($xs => uniqBy(prop('id'), $xs.concat(e)))
|
||||
},
|
||||
5: () => {
|
||||
const ids = e.tags.map(t => t[1])
|
||||
|
||||
notes.update($xs => $xs.filter(({id}) => !id.includes(ids)))
|
||||
reactions.update($xs => $xs.filter(({id}) => !id.includes(ids)))
|
||||
},
|
||||
7: () => {
|
||||
reactions.update($xs => $xs.concat(e))
|
||||
},
|
||||
})
|
||||
},
|
||||
})
|
||||
notes.update($xs => $xs.filter(({id}) => !id.includes(ids)))
|
||||
reactions.update($xs => $xs.filter(({id}) => !id.includes(ids)))
|
||||
},
|
||||
7: () => {
|
||||
reactions.update($xs => $xs.concat(e))
|
||||
},
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
const annotatedNotes = derived(
|
||||
[notes, reactions, accounts],
|
||||
([$notes, $reactions, $accounts]) => {
|
||||
const repliesById = groupBy(
|
||||
n => find(t => last(t) === 'reply', n.tags)[1],
|
||||
$notes.filter(n => n.tags.map(last).includes('reply'))
|
||||
)
|
||||
const annotatedNotes = derived(
|
||||
[notes, reactions, accounts],
|
||||
([$notes, $reactions, $accounts]) => {
|
||||
const repliesById = groupBy(
|
||||
n => find(t => last(t) === 'reply', n.tags)[1],
|
||||
$notes.filter(n => n.tags.map(last).includes('reply'))
|
||||
)
|
||||
|
||||
const reactionsById = groupBy(
|
||||
n => find(t => last(t) === 'reply', n.tags)[1],
|
||||
$reactions.filter(n => n.tags.map(last).includes('reply'))
|
||||
)
|
||||
const reactionsById = groupBy(
|
||||
n => find(t => last(t) === 'reply', n.tags)[1],
|
||||
$reactions.filter(n => n.tags.map(last).includes('reply'))
|
||||
)
|
||||
|
||||
const annotate = n => ({
|
||||
...n,
|
||||
user: $accounts[n.pubkey],
|
||||
replies: (repliesById[n.id] || []).map(reply => annotate(reply)),
|
||||
reactions: (reactionsById[n.id] || []).map(reaction => annotate(reaction)),
|
||||
})
|
||||
const annotate = n => ({
|
||||
...n,
|
||||
user: $accounts[n.pubkey],
|
||||
replies: (repliesById[n.id] || []).map(reply => annotate(reply)),
|
||||
reactions: (reactionsById[n.id] || []).map(reaction => annotate(reaction)),
|
||||
})
|
||||
|
||||
return sortBy(prop('created'), $notes.map(annotate))
|
||||
return sortBy(prop('created'), $notes.map(annotate))
|
||||
}
|
||||
)
|
||||
|
||||
const unsubscribe = annotatedNotes.subscribe(debounce(100, cb))
|
||||
|
||||
return () => {
|
||||
unsubscribe()
|
||||
|
||||
closeRequest()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const unsubscribe = annotatedNotes.subscribe(debounce(300, cb))
|
||||
// Allow caller to suspend/restart the subscription
|
||||
return start
|
||||
}
|
||||
|
||||
export const findNotesAndWatchModal = (filters, cb) => {
|
||||
const start = findNotes(filters, cb)
|
||||
|
||||
let stop = start()
|
||||
|
||||
// Suspend our subscription while we have note detail open
|
||||
// so we can avoid exceeding our concurrent subscription limit
|
||||
const unsub = modal.subscribe($modal => {
|
||||
if ($modal) {
|
||||
stop && stop()
|
||||
stop = null
|
||||
} else if (!stop) {
|
||||
// Wait for animations to complete
|
||||
setTimeout(
|
||||
() => {
|
||||
stop = start()
|
||||
},
|
||||
600
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
return () => {
|
||||
unsubscribe()
|
||||
|
||||
closeRequest()
|
||||
stop()
|
||||
unsub()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ dispatch.addMethod("account/init", async (topic, privkey) => {
|
|||
user.set({name: pubkey.slice(0, 8), privkey, pubkey})
|
||||
|
||||
// Attempt to refresh user data from the network
|
||||
const found = Boolean(await channels.getter.first({authors: [$user.pubkey]}))
|
||||
const found = Boolean(await channels.getter.first({authors: [pubkey]}))
|
||||
|
||||
// Tell the caller whether this user was found
|
||||
return {found}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {writable, get} from "svelte/store"
|
||||
import {writable} from "svelte/store"
|
||||
import {getLocalJson, setLocalJson} from "src/util/misc"
|
||||
import {nostr, channels} from 'src/state/nostr'
|
||||
import {nostr} from 'src/state/nostr'
|
||||
|
||||
export const user = writable(getLocalJson("coracle/user"))
|
||||
|
||||
|
@ -10,3 +10,4 @@ user.subscribe($user => {
|
|||
// Keep nostr in sync
|
||||
nostr.login($user?.privkey)
|
||||
})
|
||||
|
||||
|
|
Loading…
Reference in New Issue