mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-30 00:41:12 +00:00
Re-work relay selection
This commit is contained in:
parent
0fe2afb3a8
commit
5f1f9f9b69
@ -30,6 +30,7 @@ If you like Coracle and want to support its development, you can donate sats via
|
|||||||
- [ ] Attachments (a tag w/content type and url)
|
- [ ] Attachments (a tag w/content type and url)
|
||||||
- [ ] Linkify bech32 entities w/ NIP 21 https://github.com/nostr-protocol/nips/blob/master/21.md
|
- [ ] Linkify bech32 entities w/ NIP 21 https://github.com/nostr-protocol/nips/blob/master/21.md
|
||||||
- [ ] Sign in as user with one click to view things from their pubkey's perspective - do this with multiple accounts
|
- [ ] Sign in as user with one click to view things from their pubkey's perspective - do this with multiple accounts
|
||||||
|
- [ ] QR code generation/scanner to share nprofile https://cdn.jb55.com/s/d966a729777c2021.MP4
|
||||||
|
|
||||||
# Missions
|
# Missions
|
||||||
|
|
||||||
@ -73,6 +74,7 @@ If you like Coracle and want to support its development, you can donate sats via
|
|||||||
|
|
||||||
- [ ] Implement gossip model https://bountsr.org/code/2023/02/03/gossip-model.html
|
- [ ] Implement gossip model https://bountsr.org/code/2023/02/03/gossip-model.html
|
||||||
- [ ] Add nip 05 to calculation
|
- [ ] Add nip 05 to calculation
|
||||||
|
- [ ] Add connection failures to calculation
|
||||||
- [ ] Make feeds page customizable. This could potentially use the "lists" NIP
|
- [ ] Make feeds page customizable. This could potentially use the "lists" NIP
|
||||||
- [ ] Show notification at top of feeds: "Showing notes from 3 relays". Click to customize.
|
- [ ] Show notification at top of feeds: "Showing notes from 3 relays". Click to customize.
|
||||||
- [ ] Click through on relays page to view a feed for only that relay.
|
- [ ] Click through on relays page to view a feed for only that relay.
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
import {displayPerson, isLike} from 'src/util/nostr'
|
import {displayPerson, isLike} from 'src/util/nostr'
|
||||||
import {timedelta, shuffle, now, sleep} from 'src/util/misc'
|
import {timedelta, shuffle, now, sleep} from 'src/util/misc'
|
||||||
import cmd from 'src/agent/cmd'
|
import cmd from 'src/agent/cmd'
|
||||||
import {user, getRelays} from 'src/agent/helpers'
|
import {user, getUserRelays} from 'src/agent/helpers'
|
||||||
import database from 'src/agent/database'
|
import database from 'src/agent/database'
|
||||||
import keys from 'src/agent/keys'
|
import keys from 'src/agent/keys'
|
||||||
import network from 'src/agent/network'
|
import network from 'src/agent/network'
|
||||||
@ -65,6 +65,7 @@
|
|||||||
menuIsOpen.set(false)
|
menuIsOpen.set(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const {ready} = database
|
||||||
const {lastCheckedAlerts, mostRecentAlert} = alerts
|
const {lastCheckedAlerts, mostRecentAlert} = alerts
|
||||||
const {lastCheckedByPubkey, mostRecentByPubkey} = messages
|
const {lastCheckedByPubkey, mostRecentByPubkey} = messages
|
||||||
|
|
||||||
@ -97,7 +98,7 @@
|
|||||||
|
|
||||||
const alertSlowConnections = () => {
|
const alertSlowConnections = () => {
|
||||||
// Only notify about relays the user is actually subscribed to
|
// Only notify about relays the user is actually subscribed to
|
||||||
const relayUrls = pluck('url', getRelays())
|
const relayUrls = pluck('url', getUserRelays('read'))
|
||||||
|
|
||||||
// Prune connections we haven't used in a while
|
// Prune connections we haven't used in a while
|
||||||
pool.getConnections()
|
pool.getConnections()
|
||||||
@ -201,6 +202,7 @@
|
|||||||
|
|
||||||
<Router {url}>
|
<Router {url}>
|
||||||
<div use:links class="h-full">
|
<div use:links class="h-full">
|
||||||
|
{#if $ready}
|
||||||
<div class="pt-16 text-white h-full lg:ml-56">
|
<div class="pt-16 text-white h-full lg:ml-56">
|
||||||
<Route path="/alerts" component={Alerts} />
|
<Route path="/alerts" component={Alerts} />
|
||||||
<Route path="/search/:activeTab" component={Search} />
|
<Route path="/search/:activeTab" component={Search} />
|
||||||
@ -234,6 +236,7 @@
|
|||||||
</Route>
|
</Route>
|
||||||
<Route path="*" component={NotFound} />
|
<Route path="*" component={NotFound} />
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<ul
|
<ul
|
||||||
class="py-20 w-56 bg-dark fixed top-0 bottom-0 left-0 transition-all shadow-xl
|
class="py-20 w-56 bg-dark fixed top-0 bottom-0 left-0 transition-all shadow-xl
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import {prop, pick, join, uniqBy, last} from 'ramda'
|
import {prop, pick, join, uniqBy, last} from 'ramda'
|
||||||
import {get} from 'svelte/store'
|
import {get} from 'svelte/store'
|
||||||
import {first} from "hurdak/lib/hurdak"
|
import {first} from "hurdak/lib/hurdak"
|
||||||
import {Tags, isRelay, roomAttrs, displayPerson} from 'src/util/nostr'
|
import {roomAttrs, displayPerson} from 'src/util/nostr'
|
||||||
import {getWriteRelays} from 'src/agent/helpers'
|
import {getBestRelay} from 'src/agent/helpers'
|
||||||
import database from 'src/agent/database'
|
import database from 'src/agent/database'
|
||||||
import network from 'src/agent/network'
|
import network from 'src/agent/network'
|
||||||
import keys from 'src/agent/keys'
|
import keys from 'src/agent/keys'
|
||||||
@ -29,15 +29,14 @@ const createChatMessage = (relays, roomId, content) =>
|
|||||||
publishEvent(relays, 42, {content, tags: [["e", roomId, prop('url', first(relays)), "root"]]})
|
publishEvent(relays, 42, {content, tags: [["e", roomId, prop('url', first(relays)), "root"]]})
|
||||||
|
|
||||||
const createDirectMessage = (relays, pubkey, content) =>
|
const createDirectMessage = (relays, pubkey, content) =>
|
||||||
// todo, encrypt messages
|
|
||||||
publishEvent(relays, 4, {content, tags: [["p", pubkey]]})
|
publishEvent(relays, 4, {content, tags: [["p", pubkey]]})
|
||||||
|
|
||||||
const createNote = (relays, content, mentions = [], topics = []) => {
|
const createNote = (relays, content, mentions = [], topics = []) => {
|
||||||
mentions = mentions.map(p => {
|
mentions = mentions.map(pubkey => {
|
||||||
const {url} = first(getWriteRelays(p))
|
const name = displayPerson(database.getPersonWithFallback(pubkey))
|
||||||
const name = displayPerson(database.getPersonWithFallback(p))
|
const {url} = getBestRelay(pubkey, 'write')
|
||||||
|
|
||||||
return ["p", p, url, name]
|
return ["p", pubkey, url, name]
|
||||||
})
|
})
|
||||||
|
|
||||||
topics = topics.map(t => ["t", t])
|
topics = topics.map(t => ["t", t])
|
||||||
@ -46,7 +45,7 @@ const createNote = (relays, content, mentions = [], topics = []) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const createReaction = (relays, note, content) => {
|
const createReaction = (relays, note, content) => {
|
||||||
const {url} = getBestRelay(relays, note)
|
const {url} = getBestRelay(note.pubkey, 'write')
|
||||||
const tags = uniqBy(
|
const tags = uniqBy(
|
||||||
join(':'),
|
join(':'),
|
||||||
note.tags
|
note.tags
|
||||||
@ -59,10 +58,10 @@ const createReaction = (relays, note, content) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const createReply = (relays, note, content, mentions = [], topics = []) => {
|
const createReply = (relays, note, content, mentions = [], topics = []) => {
|
||||||
mentions = mentions.map(p => ["p", p, prop('url', first(getWriteRelays(p)))])
|
mentions = mentions.map(pubkey => ["p", pubkey, prop('url', getBestRelay(pubkey))])
|
||||||
topics = topics.map(t => ["t", t])
|
topics = topics.map(t => ["t", t])
|
||||||
|
|
||||||
const {url} = getBestRelay(relays, note)
|
const {url} = getBestRelay(note.pubkey, 'write')
|
||||||
const tags = uniqBy(
|
const tags = uniqBy(
|
||||||
join(':'),
|
join(':'),
|
||||||
note.tags
|
note.tags
|
||||||
@ -80,24 +79,6 @@ const deleteEvent = (relays, ids) =>
|
|||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
|
|
||||||
const getBestRelay = (relays, event) => {
|
|
||||||
// Find the best relay, based on reply, root, or pubkey. Fall back to a
|
|
||||||
// relay we're going to send the event to
|
|
||||||
const tags = Tags.from(event).type("e")
|
|
||||||
const reply = tags.mark("reply").values().first()
|
|
||||||
const root = tags.mark("root").values().first()
|
|
||||||
|
|
||||||
if (isRelay(reply)) {
|
|
||||||
return reply
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isRelay(root)) {
|
|
||||||
return root
|
|
||||||
}
|
|
||||||
|
|
||||||
return first(getWriteRelays(event.pubkey).concat(relays))
|
|
||||||
}
|
|
||||||
|
|
||||||
const publishEvent = (relays, kind, {content = '', tags = []} = {}) => {
|
const publishEvent = (relays, kind, {content = '', tags = []} = {}) => {
|
||||||
if (relays.length === 0) {
|
if (relays.length === 0) {
|
||||||
throw new Error("Unable to publish, no relays specified")
|
throw new Error("Unable to publish, no relays specified")
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import {debounce} from 'throttle-debounce'
|
import {debounce} from 'throttle-debounce'
|
||||||
import {is, prop, without} from 'ramda'
|
import {is, prop, find, without, pluck, all, identity} from 'ramda'
|
||||||
import {writable} from 'svelte/store'
|
import {writable, derived} from 'svelte/store'
|
||||||
import {switcherFn, createMap, ensurePlural, first} from 'hurdak/lib/hurdak'
|
import {switcherFn, createMap, ensurePlural} from 'hurdak/lib/hurdak'
|
||||||
import {defer, asyncIterableToArray} from 'src/util/misc'
|
import {defer, where, asyncIterableToArray} from 'src/util/misc'
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
|
|
||||||
@ -18,8 +18,9 @@ type Table = {
|
|||||||
patch: (data: object) => void
|
patch: (data: object) => void
|
||||||
bulkPut: (data: object) => void
|
bulkPut: (data: object) => void
|
||||||
bulkPatch: (data: object) => void
|
bulkPatch: (data: object) => void
|
||||||
all: (where?: object) => Promise<any>
|
iter: (spec?: object) => Promise<Array<Record<string, any>>>
|
||||||
get: (key: string) => any
|
all: (spec?: object) => Array<Record<string, any>>
|
||||||
|
get: (key: string) => Record<string, any>
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plumbing
|
// Plumbing
|
||||||
@ -142,6 +143,8 @@ const defineTable = (name: string, pk: string): Table => {
|
|||||||
let listeners = []
|
let listeners = []
|
||||||
let data = {}
|
let data = {}
|
||||||
|
|
||||||
|
const ready = writable(false)
|
||||||
|
|
||||||
const subscribe = f => {
|
const subscribe = f => {
|
||||||
listeners.push(f)
|
listeners.push(f)
|
||||||
|
|
||||||
@ -196,8 +199,10 @@ const defineTable = (name: string, pk: string): Table => {
|
|||||||
const put = item => bulkPut(createMap(pk, [item]))
|
const put = item => bulkPut(createMap(pk, [item]))
|
||||||
const patch = item => bulkPatch(createMap(pk, [item]))
|
const patch = item => bulkPatch(createMap(pk, [item]))
|
||||||
|
|
||||||
const all = (where = {}) => asyncIterableToArray(iterate(name, where), prop('v'))
|
const toArray = () => Object.values(data)
|
||||||
const one = (where = {}) => first(all(where))
|
const iter = (spec = {}) => asyncIterableToArray(iterate(name, spec), prop('v'))
|
||||||
|
const all = (spec = {}) => toArray().filter(where(spec))
|
||||||
|
const one = (spec = {}) => find(where(spec), toArray())
|
||||||
const get = k => data[k]
|
const get = k => data[k]
|
||||||
|
|
||||||
// Sync from storage initially
|
// Sync from storage initially
|
||||||
@ -208,9 +213,13 @@ const defineTable = (name: string, pk: string): Table => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setAndNotify(initialData)
|
setAndNotify(initialData)
|
||||||
|
ready.set(true)
|
||||||
})()
|
})()
|
||||||
|
|
||||||
registry[name] = {name, subscribe, bulkPut, bulkPatch, put, patch, all, one, get}
|
registry[name] = {
|
||||||
|
name, subscribe, bulkPut, bulkPatch, put, patch, toArray, iter, all, one, get,
|
||||||
|
ready,
|
||||||
|
}
|
||||||
|
|
||||||
return registry[name]
|
return registry[name]
|
||||||
}
|
}
|
||||||
@ -277,8 +286,10 @@ const getPersonWithFallback = pubkey => people.get(pubkey) || {pubkey}
|
|||||||
|
|
||||||
const clearAll = () => Promise.all(Object.keys(registry).map(clear))
|
const clearAll = () => Promise.all(Object.keys(registry).map(clear))
|
||||||
|
|
||||||
|
const ready = derived(pluck('ready', Object.values(registry)), all(identity))
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getItem, setItem, removeItem, length, clear, keys, iterate, watch,
|
getItem, setItem, removeItem, length, clear, keys, iterate, watch,
|
||||||
getPersonWithFallback, clearAll, people, rooms, messages, alerts, relays,
|
getPersonWithFallback, clearAll, people, rooms, messages, alerts, relays,
|
||||||
routes,
|
routes, ready,
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import type {Person} from 'src/util/types'
|
import type {Person} from 'src/util/types'
|
||||||
import type {Readable} from 'svelte/store'
|
import type {Readable} from 'svelte/store'
|
||||||
import {uniq, reject, last, propEq, uniqBy, prop} from 'ramda'
|
import {isEmpty, pick, identity, sortBy, uniq, reject, groupBy, last, propEq, uniqBy, prop} from 'ramda'
|
||||||
|
import {first} from 'hurdak/lib/hurdak'
|
||||||
import {derived, get} from 'svelte/store'
|
import {derived, get} from 'svelte/store'
|
||||||
import {Tags} from 'src/util/nostr'
|
import {Tags} from 'src/util/nostr'
|
||||||
import {now, timedelta} from 'src/util/misc'
|
import {now, timedelta} from 'src/util/misc'
|
||||||
@ -37,27 +38,33 @@ export const getFollows = pubkey => {
|
|||||||
return Tags.wrap(person.petnames || defaults.petnames).values().all()
|
return Tags.wrap(person.petnames || defaults.petnames).values().all()
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getRelays = (pubkey?: string) => {
|
export const getPersonRelays = (person, mode = 'all') => {
|
||||||
let relays = database.getPersonWithFallback(pubkey).relays
|
const relays = isEmpty(person?.relays || []) ? defaults.relays : person.relays
|
||||||
|
|
||||||
if (!relays?.length) {
|
return reject(propEq(mode, '!'), relays)
|
||||||
relays = database.getPersonWithFallback(get(keys.pubkey)).relays
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!relays?.length) {
|
|
||||||
relays = defaults.relays
|
|
||||||
}
|
|
||||||
|
|
||||||
return relays
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getWriteRelays = (...args) =>
|
export const getUserRelays = (mode = 'all') =>
|
||||||
reject(propEq('write', '!'), getRelays(...args))
|
getPersonRelays(get(user), mode)
|
||||||
|
|
||||||
|
export const getPubkeyRelays = (pubkey, mode = 'all') =>
|
||||||
|
getPersonRelays(database.people.get(pubkey), mode)
|
||||||
|
|
||||||
|
export const getTopRelays = (pubkeys, mode = 'all') => {
|
||||||
|
const routes = database.routes.all({mode, pubkey: pubkeys})
|
||||||
|
const routesByPubkey = groupBy(prop('pubkey'), routes)
|
||||||
|
const selectRoute = k => first(sortBy(prop('score'), routesByPubkey[k] || []))
|
||||||
|
|
||||||
|
return uniqBy(prop('url'), pubkeys.map(selectRoute).filter(identity)).map(pick(['url']))
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getBestRelay = (pubkey, mode = 'all') =>
|
||||||
|
first(getTopRelays([pubkey], mode).concat(getPubkeyRelays(pubkey, mode)))
|
||||||
|
|
||||||
export const getEventRelays = event => {
|
export const getEventRelays = event => {
|
||||||
return uniqBy(
|
return uniqBy(
|
||||||
prop('url'),
|
prop('url'),
|
||||||
getRelays(event.pubkey)
|
getPubkeyRelays(event.pubkey, 'write')
|
||||||
.concat(Tags.from(event).relays())
|
.concat(Tags.from(event).relays())
|
||||||
.concat({url: event.seen_on})
|
.concat({url: event.seen_on})
|
||||||
)
|
)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import lf from 'localforage'
|
import lf from 'localforage'
|
||||||
import memoryStorageDriver from 'localforage-memoryStorageDriver'
|
import memoryStorageDriver from 'localforage-memoryStorageDriver'
|
||||||
import {is, complement, equals, isNil, pipe, prop, identity, allPass} from 'ramda'
|
|
||||||
import {switcherFn} from 'hurdak/lib/hurdak'
|
import {switcherFn} from 'hurdak/lib/hurdak'
|
||||||
|
import {where} from 'src/util/misc'
|
||||||
|
|
||||||
// Firefox private mode doesn't have access to any storage options
|
// Firefox private mode doesn't have access to any storage options
|
||||||
lf.defineDriver(memoryStorageDriver)
|
lf.defineDriver(memoryStorageDriver)
|
||||||
@ -28,41 +28,9 @@ addEventListener('message', async ({data: {topic, payload, channel}}) => {
|
|||||||
reply('localforage.return', result)
|
reply('localforage.return', result)
|
||||||
},
|
},
|
||||||
'localforage.iterate': async () => {
|
'localforage.iterate': async () => {
|
||||||
const {storeName, where} = payload
|
const matchesFilter = where(payload.where)
|
||||||
const matchesFilter = allPass(
|
|
||||||
Object.entries(where)
|
|
||||||
.map(([key, value]) => {
|
|
||||||
let [field, operator = 'eq'] = key.split(':')
|
|
||||||
let test, modifier = identity
|
|
||||||
|
|
||||||
if (operator.startsWith('!')) {
|
getStore(payload.storeName).iterate(
|
||||||
operator = operator.slice(1)
|
|
||||||
modifier = complement
|
|
||||||
}
|
|
||||||
|
|
||||||
if (operator === 'eq' && is(Array, value)) {
|
|
||||||
test = v => value.includes(v)
|
|
||||||
} else if (operator === 'eq') {
|
|
||||||
test = equals(value)
|
|
||||||
} else if (operator === 'lt') {
|
|
||||||
test = v => (v || 0) < value
|
|
||||||
} else if (operator === 'lte') {
|
|
||||||
test = v => (v || 0) <= value
|
|
||||||
} else if (operator === 'gt') {
|
|
||||||
test = v => (v || 0) > value
|
|
||||||
} else if (operator === 'gte') {
|
|
||||||
test = v => (v || 0) >= value
|
|
||||||
} else if (operator === 'nil') {
|
|
||||||
test = isNil
|
|
||||||
} else {
|
|
||||||
throw new Error(`Invalid operator ${operator}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
return pipe(prop(field), modifier(test))
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
getStore(storeName).iterate(
|
|
||||||
(v, k, i) => {
|
(v, k, i) => {
|
||||||
if (matchesFilter(v)) {
|
if (matchesFilter(v)) {
|
||||||
reply('localforage.item', {v, k, i})
|
reply('localforage.item', {v, k, i})
|
||||||
|
@ -5,7 +5,7 @@ import {createMap, ellipsize} from 'hurdak/lib/hurdak'
|
|||||||
import {get} from 'svelte/store'
|
import {get} from 'svelte/store'
|
||||||
import {renderContent} from 'src/util/html'
|
import {renderContent} from 'src/util/html'
|
||||||
import {Tags, displayPerson, findReplyId} from 'src/util/nostr'
|
import {Tags, displayPerson, findReplyId} from 'src/util/nostr'
|
||||||
import {user, getRelays, getWriteRelays} from 'src/agent/helpers'
|
import {user, getUserRelays} from 'src/agent/helpers'
|
||||||
import defaults from 'src/agent/defaults'
|
import defaults from 'src/agent/defaults'
|
||||||
import database from 'src/agent/database'
|
import database from 'src/agent/database'
|
||||||
import network from 'src/agent/network'
|
import network from 'src/agent/network'
|
||||||
@ -18,11 +18,13 @@ import {toast, routes, modal, settings, logUsage} from 'src/app/ui'
|
|||||||
export {toast, modal, settings, alerts, messages, logUsage}
|
export {toast, modal, settings, alerts, messages, logUsage}
|
||||||
|
|
||||||
export const loadAppData = pubkey => {
|
export const loadAppData = pubkey => {
|
||||||
|
const relays = getUserRelays('read')
|
||||||
|
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
network.loadNetwork(getRelays(), pubkey),
|
network.loadNetwork(relays, pubkey),
|
||||||
alerts.load(getRelays(), pubkey),
|
alerts.load(relays, pubkey),
|
||||||
alerts.listen(getRelays(), pubkey),
|
alerts.listen(relays, pubkey),
|
||||||
messages.listen(getRelays(), pubkey),
|
messages.listen(relays, pubkey),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +41,7 @@ export const login = async ({privkey, pubkey}: {privkey?: string, pubkey?: strin
|
|||||||
loadAppData(pubkey)
|
loadAppData(pubkey)
|
||||||
|
|
||||||
// Load our user so we can populate network and show profile info
|
// Load our user so we can populate network and show profile info
|
||||||
await network.loadPeople(getRelays(), [pubkey])
|
await network.loadPeople(getUserRelays('read'), [pubkey])
|
||||||
|
|
||||||
// Not ideal, but the network tab depends on the user's social network being
|
// Not ideal, but the network tab depends on the user's social network being
|
||||||
// loaded, so put them on global when they first log in so we're not slowing
|
// loaded, so put them on global when they first log in so we're not slowing
|
||||||
@ -73,7 +75,7 @@ export const removeRelay = async url => {
|
|||||||
defaults.relays = modify(defaults.relays)
|
defaults.relays = modify(defaults.relays)
|
||||||
|
|
||||||
if (person) {
|
if (person) {
|
||||||
await cmd.setRelays(getWriteRelays(), modify(person.relays || []))
|
await cmd.setRelays(getUserRelays('write'), modify(person.relays || []))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +87,7 @@ export const setRelayWriteCondition = async (url, write) => {
|
|||||||
defaults.relays = modify(defaults.relays)
|
defaults.relays = modify(defaults.relays)
|
||||||
|
|
||||||
if (person) {
|
if (person) {
|
||||||
await cmd.setRelays(getWriteRelays(), modify(person.relays || []))
|
await cmd.setRelays(getUserRelays('write'), modify(person.relays || []))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
let prevContent = ''
|
let prevContent = ''
|
||||||
let search
|
let search
|
||||||
|
|
||||||
database.people.all({'name:!nil': null}).then(people => {
|
database.people.iter({'name:!nil': null}).then(people => {
|
||||||
search = fuzzy(people, {keys: ["name", "pubkey"]})
|
search = fuzzy(people, {keys: ["name", "pubkey"]})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
import {nip19} from 'nostr-tools'
|
import {nip19} from 'nostr-tools'
|
||||||
import {navigate} from "svelte-routing"
|
import {navigate} from "svelte-routing"
|
||||||
import {fuzzy} from "src/util/misc"
|
import {fuzzy} from "src/util/misc"
|
||||||
import {getRelays, user} from 'src/agent/helpers'
|
import {getUserRelays, getTopRelays, user} from 'src/agent/helpers'
|
||||||
import network from 'src/agent/network'
|
import network from 'src/agent/network'
|
||||||
import database from 'src/agent/database'
|
import database from 'src/agent/database'
|
||||||
import {modal, messages} from 'src/app'
|
import {modal, messages} from 'src/app'
|
||||||
@ -24,7 +24,7 @@
|
|||||||
const messages = await database.messages.all()
|
const messages = await database.messages.all()
|
||||||
const pubkeys = without([$user.pubkey], uniq(messages.flatMap(m => [m.pubkey, m.recipient])))
|
const pubkeys = without([$user.pubkey], uniq(messages.flatMap(m => [m.pubkey, m.recipient])))
|
||||||
|
|
||||||
await network.loadPeople(getRelays(), pubkeys)
|
await network.loadPeople(getTopRelays(pubkeys, 'write'), pubkeys)
|
||||||
|
|
||||||
return sortBy(k => -(mostRecentByPubkey[k] || 0), pubkeys)
|
return sortBy(k => -(mostRecentByPubkey[k] || 0), pubkeys)
|
||||||
.map(k => ({type: 'npub', id: k, ...database.getPersonWithFallback(k)}))
|
.map(k => ({type: 'npub', id: k, ...database.getPersonWithFallback(k)}))
|
||||||
@ -58,7 +58,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
const sub = network.listen(getRelays(), [{kinds: [40, 41]}])
|
const sub = network.listen(getUserRelays('read'), [{kinds: [40, 41]}])
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
sub.then(s => {
|
sub.then(s => {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
import {nip19} from 'nostr-tools'
|
import {nip19} from 'nostr-tools'
|
||||||
import {now, batch} from 'src/util/misc'
|
import {now, batch} from 'src/util/misc'
|
||||||
import Channel from 'src/partials/Channel.svelte'
|
import Channel from 'src/partials/Channel.svelte'
|
||||||
import {getRelays, user} from 'src/agent/helpers'
|
import {getEventRelays, user} from 'src/agent/helpers'
|
||||||
import database from 'src/agent/database'
|
import database from 'src/agent/database'
|
||||||
import network from 'src/agent/network'
|
import network from 'src/agent/network'
|
||||||
import {modal} from 'src/app'
|
import {modal} from 'src/app'
|
||||||
@ -11,21 +11,11 @@
|
|||||||
|
|
||||||
export let entity
|
export let entity
|
||||||
|
|
||||||
let {data: roomId} = nip19.decode(entity) as {data: string}
|
const {data: roomId} = nip19.decode(entity) as {data: string}
|
||||||
let room = database.watch('rooms', rooms => rooms.get(roomId))
|
const room = database.watch('rooms', rooms => rooms.get(roomId))
|
||||||
|
|
||||||
const getRoomRelays = () => {
|
|
||||||
let relays = getRelays()
|
|
||||||
|
|
||||||
if ($room) {
|
|
||||||
relays = relays.concat(getRelays($room.pubkey))
|
|
||||||
}
|
|
||||||
|
|
||||||
return relays
|
|
||||||
}
|
|
||||||
|
|
||||||
const listenForMessages = async cb => {
|
const listenForMessages = async cb => {
|
||||||
const relays = getRoomRelays()
|
const relays = getEventRelays($room)
|
||||||
|
|
||||||
return network.listen(
|
return network.listen(
|
||||||
relays,
|
relays,
|
||||||
@ -43,7 +33,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const loadMessages = async ({until, limit}) => {
|
const loadMessages = async ({until, limit}) => {
|
||||||
const relays = getRoomRelays()
|
const relays = getEventRelays($room)
|
||||||
const events = await network.load(relays, {kinds: [42], '#e': [roomId], until, limit})
|
const events = await network.load(relays, {kinds: [42], '#e': [roomId], until, limit})
|
||||||
|
|
||||||
if (events.length) {
|
if (events.length) {
|
||||||
@ -58,7 +48,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const sendMessage = content =>
|
const sendMessage = content =>
|
||||||
cmd.createChatMessage(getRoomRelays(), roomId, content)
|
cmd.createChatMessage(getEventRelays($room), roomId, content)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Channel
|
<Channel
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
import {personKinds} from 'src/util/nostr'
|
import {personKinds} from 'src/util/nostr'
|
||||||
import {batch, now} from 'src/util/misc'
|
import {batch, now} from 'src/util/misc'
|
||||||
import Channel from 'src/partials/Channel.svelte'
|
import Channel from 'src/partials/Channel.svelte'
|
||||||
import {getRelays, getWriteRelays, user} from 'src/agent/helpers'
|
import {getUserRelays, getPubkeyRelays, user} from 'src/agent/helpers'
|
||||||
import database from 'src/agent/database'
|
import database from 'src/agent/database'
|
||||||
import network from 'src/agent/network'
|
import network from 'src/agent/network'
|
||||||
import keys from 'src/agent/keys'
|
import keys from 'src/agent/keys'
|
||||||
@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
messages.lastCheckedByPubkey.update($obj => ({...$obj, [pubkey]: now()}))
|
messages.lastCheckedByPubkey.update($obj => ({...$obj, [pubkey]: now()}))
|
||||||
|
|
||||||
|
const getRelays = () => getUserRelays('write').concat(getPubkeyRelays(pubkey, 'write'))
|
||||||
|
|
||||||
const decryptMessages = async events => {
|
const decryptMessages = async events => {
|
||||||
// Gotta do it in serial because of extension limitations
|
// Gotta do it in serial because of extension limitations
|
||||||
for (const event of events) {
|
for (const event of events) {
|
||||||
@ -32,7 +34,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const listenForMessages = cb => network.listen(
|
const listenForMessages = cb => network.listen(
|
||||||
getRelays().concat(getRelays(pubkey)),
|
getRelays(),
|
||||||
[{kinds: personKinds, authors: [pubkey]},
|
[{kinds: personKinds, authors: [pubkey]},
|
||||||
{kinds: [4], authors: [$user.pubkey], '#p': [pubkey]},
|
{kinds: [4], authors: [$user.pubkey], '#p': [pubkey]},
|
||||||
{kinds: [4], authors: [pubkey], '#p': [$user.pubkey]}],
|
{kinds: [4], authors: [pubkey], '#p': [$user.pubkey]}],
|
||||||
@ -55,9 +57,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const sendMessage = async content => {
|
const sendMessage = async content => {
|
||||||
const relays = getWriteRelays().concat(getRelays(pubkey))
|
|
||||||
const cyphertext = await crypt.encrypt(pubkey, content)
|
const cyphertext = await crypt.encrypt(pubkey, content)
|
||||||
const event = await cmd.createDirectMessage(relays, pubkey, cyphertext)
|
const event = await cmd.createDirectMessage(getRelays(), pubkey, cyphertext)
|
||||||
|
|
||||||
// Return unencrypted content so we can display it immediately
|
// Return unencrypted content so we can display it immediately
|
||||||
return {...event, content}
|
return {...event, content}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
import {last, find, reject} from 'ramda'
|
import {last, find, reject} from 'ramda'
|
||||||
import {onMount, onDestroy} from 'svelte'
|
import {onMount, onDestroy} from 'svelte'
|
||||||
import {nip19} from 'nostr-tools'
|
import {nip19} from 'nostr-tools'
|
||||||
import {first} from 'hurdak/lib/hurdak'
|
|
||||||
import {fly} from 'svelte/transition'
|
import {fly} from 'svelte/transition'
|
||||||
import {navigate} from 'svelte-routing'
|
import {navigate} from 'svelte-routing'
|
||||||
import {renderContent} from 'src/util/html'
|
import {renderContent} from 'src/util/html'
|
||||||
@ -14,7 +13,7 @@
|
|||||||
import Notes from "src/views/person/Notes.svelte"
|
import Notes from "src/views/person/Notes.svelte"
|
||||||
import Likes from "src/views/person/Likes.svelte"
|
import Likes from "src/views/person/Likes.svelte"
|
||||||
import Network from "src/views/person/Network.svelte"
|
import Network from "src/views/person/Network.svelte"
|
||||||
import {getRelays, getWriteRelays, user} from "src/agent/helpers"
|
import {getPubkeyRelays, getUserRelays, user} from "src/agent/helpers"
|
||||||
import network from "src/agent/network"
|
import network from "src/agent/network"
|
||||||
import keys from "src/agent/keys"
|
import keys from "src/agent/keys"
|
||||||
import database from "src/agent/database"
|
import database from "src/agent/database"
|
||||||
@ -24,7 +23,7 @@
|
|||||||
|
|
||||||
export let npub
|
export let npub
|
||||||
export let activeTab
|
export let activeTab
|
||||||
export let relays = null
|
export let relays = []
|
||||||
|
|
||||||
let subs = []
|
let subs = []
|
||||||
let pubkey = nip19.decode(npub).data as string
|
let pubkey = nip19.decode(npub).data as string
|
||||||
@ -37,22 +36,27 @@
|
|||||||
$: following = find(t => t[1] === pubkey, $user?.petnames || [])
|
$: following = find(t => t[1] === pubkey, $user?.petnames || [])
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
|
// Add all the relays we know the person uses
|
||||||
|
relays = relays.concat(getPubkeyRelays(pubkey))
|
||||||
|
|
||||||
// Refresh our person if needed
|
// Refresh our person if needed
|
||||||
network.loadPeople(relays || getRelays(pubkey), [pubkey]).then(() => {
|
network.loadPeople(relays, [pubkey]).then(() => {
|
||||||
person = database.getPersonWithFallback(pubkey)
|
person = database.getPersonWithFallback(pubkey)
|
||||||
loading = false
|
loading = false
|
||||||
})
|
})
|
||||||
|
|
||||||
// Get our followers count
|
// Get our followers count
|
||||||
subs.push(await network.listen(
|
subs.push(
|
||||||
relays || getRelays(pubkey),
|
await network.listen(
|
||||||
[{kinds: [3], '#p': [pubkey]}],
|
relays,
|
||||||
e => {
|
[{kinds: [3], '#p': [pubkey]}],
|
||||||
followers.add(e.pubkey)
|
e => {
|
||||||
followersCount = followers.size
|
followers.add(e.pubkey)
|
||||||
},
|
followersCount = followers.size
|
||||||
{shouldProcess: false},
|
},
|
||||||
))
|
{shouldProcess: false},
|
||||||
|
)
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
@ -74,17 +78,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const follow = async () => {
|
const follow = async () => {
|
||||||
const relay = first(relays || getRelays(pubkey))
|
const tag = ["p", pubkey, relays[0].url, person.name || ""]
|
||||||
const tag = ["p", pubkey, relay.url, person.name || ""]
|
|
||||||
const petnames = reject(t => t[1] === pubkey, $user.petnames).concat([tag])
|
const petnames = reject(t => t[1] === pubkey, $user.petnames).concat([tag])
|
||||||
|
|
||||||
cmd.setPetnames(getWriteRelays(), petnames)
|
cmd.setPetnames(getUserRelays('write'), petnames)
|
||||||
}
|
}
|
||||||
|
|
||||||
const unfollow = async () => {
|
const unfollow = async () => {
|
||||||
const petnames = reject(t => t[1] === pubkey, $user.petnames)
|
const petnames = reject(t => t[1] === pubkey, $user.petnames)
|
||||||
|
|
||||||
cmd.setPetnames(getWriteRelays(), petnames)
|
cmd.setPetnames(getUserRelays('write'), petnames)
|
||||||
}
|
}
|
||||||
|
|
||||||
const openAdvanced = () => {
|
const openAdvanced = () => {
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
import Button from "src/partials/Button.svelte"
|
import Button from "src/partials/Button.svelte"
|
||||||
import Content from "src/partials/Content.svelte"
|
import Content from "src/partials/Content.svelte"
|
||||||
import Heading from "src/partials/Heading.svelte"
|
import Heading from "src/partials/Heading.svelte"
|
||||||
import {user, getWriteRelays} from "src/agent/helpers"
|
import {user, getUserRelays} from "src/agent/helpers"
|
||||||
import cmd from "src/agent/cmd"
|
import cmd from "src/agent/cmd"
|
||||||
import {toast} from "src/app"
|
import {toast} from "src/app"
|
||||||
import {routes} from "src/app/ui"
|
import {routes} from "src/app/ui"
|
||||||
@ -45,7 +45,7 @@
|
|||||||
const submit = async event => {
|
const submit = async event => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
||||||
await cmd.updateUser(getWriteRelays(), values)
|
await cmd.updateUser(getUserRelays('write'), values)
|
||||||
|
|
||||||
navigate(routes.person($user.pubkey, 'profile'))
|
navigate(routes.person($user.pubkey, 'profile'))
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {debounce} from 'throttle-debounce'
|
import {debounce} from 'throttle-debounce'
|
||||||
import {pluck, identity, sortBy} from "ramda"
|
import {allPass, prop, pipe, isNil, complement, equals, is, pluck, sum, identity, sortBy} from "ramda"
|
||||||
import Fuse from "fuse.js/dist/fuse.min.js"
|
import Fuse from "fuse.js/dist/fuse.min.js"
|
||||||
import {writable} from 'svelte/store'
|
import {writable} from 'svelte/store'
|
||||||
import {isObject} from 'hurdak/lib/hurdak'
|
import {isObject} from 'hurdak/lib/hurdak'
|
||||||
@ -145,7 +145,7 @@ export const getLastSync = (k, fallback = 0) => {
|
|||||||
export class Cursor {
|
export class Cursor {
|
||||||
until: number
|
until: number
|
||||||
limit: number
|
limit: number
|
||||||
constructor(limit = 10) {
|
constructor(limit = 50) {
|
||||||
this.until = now()
|
this.until = now()
|
||||||
this.limit = limit
|
this.limit = limit
|
||||||
}
|
}
|
||||||
@ -197,3 +197,40 @@ export const asyncIterableToArray = async (it, f = identity) => {
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const avg = xs => sum(xs) / xs.length
|
||||||
|
|
||||||
|
export const where = filters =>
|
||||||
|
allPass(
|
||||||
|
Object.entries(filters)
|
||||||
|
.map(([key, value]) => {
|
||||||
|
/* eslint prefer-const: 0 */
|
||||||
|
let [field, operator = 'eq'] = key.split(':')
|
||||||
|
let test, modifier = identity
|
||||||
|
|
||||||
|
if (operator.startsWith('!')) {
|
||||||
|
operator = operator.slice(1)
|
||||||
|
modifier = complement
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operator === 'eq' && is(Array, value)) {
|
||||||
|
test = v => (value as Array<any>).includes(v)
|
||||||
|
} else if (operator === 'eq') {
|
||||||
|
test = equals(value)
|
||||||
|
} else if (operator === 'lt') {
|
||||||
|
test = v => (v || 0) < value
|
||||||
|
} else if (operator === 'lte') {
|
||||||
|
test = v => (v || 0) <= value
|
||||||
|
} else if (operator === 'gt') {
|
||||||
|
test = v => (v || 0) > value
|
||||||
|
} else if (operator === 'gte') {
|
||||||
|
test = v => (v || 0) >= value
|
||||||
|
} else if (operator === 'nil') {
|
||||||
|
test = isNil
|
||||||
|
} else {
|
||||||
|
throw new Error(`Invalid operator ${operator}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
return pipe(prop(field), modifier(test))
|
||||||
|
})
|
||||||
|
)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
import Content from "src/partials/Content.svelte"
|
import Content from "src/partials/Content.svelte"
|
||||||
import Textarea from "src/partials/Textarea.svelte"
|
import Textarea from "src/partials/Textarea.svelte"
|
||||||
import Button from "src/partials/Button.svelte"
|
import Button from "src/partials/Button.svelte"
|
||||||
import {getWriteRelays} from 'src/agent/helpers'
|
import {getUserRelays} from 'src/agent/helpers'
|
||||||
import database from 'src/agent/database'
|
import database from 'src/agent/database'
|
||||||
import cmd from "src/agent/cmd"
|
import cmd from "src/agent/cmd"
|
||||||
import {toast, modal} from "src/app"
|
import {toast, modal} from "src/app"
|
||||||
@ -36,8 +36,8 @@
|
|||||||
toast.show("error", "Please enter a name for your room.")
|
toast.show("error", "Please enter a name for your room.")
|
||||||
} else {
|
} else {
|
||||||
const event = room.id
|
const event = room.id
|
||||||
? await cmd.updateRoom(getWriteRelays(), room)
|
? await cmd.updateRoom(getUserRelays('write'), room)
|
||||||
: await cmd.createRoom(getWriteRelays(), room)
|
: await cmd.createRoom(getUserRelays('write'), room)
|
||||||
|
|
||||||
await database.rooms.patch({id: room.id || event.id, joined: true})
|
await database.rooms.patch({id: room.id || event.id, joined: true})
|
||||||
|
|
||||||
|
@ -13,13 +13,13 @@
|
|||||||
import Content from "src/partials/Content.svelte"
|
import Content from "src/partials/Content.svelte"
|
||||||
import Modal from "src/partials/Modal.svelte"
|
import Modal from "src/partials/Modal.svelte"
|
||||||
import Heading from 'src/partials/Heading.svelte'
|
import Heading from 'src/partials/Heading.svelte'
|
||||||
import {user, getWriteRelays} from "src/agent/helpers"
|
import {user, getUserRelays} from "src/agent/helpers"
|
||||||
import database from 'src/agent/database'
|
import database from 'src/agent/database'
|
||||||
import cmd from "src/agent/cmd"
|
import cmd from "src/agent/cmd"
|
||||||
import {toast, modal} from "src/app"
|
import {toast, modal} from "src/app"
|
||||||
|
|
||||||
let input = null
|
let input = null
|
||||||
let relays = getWriteRelays()
|
let relays = getUserRelays('write')
|
||||||
let showSettings = false
|
let showSettings = false
|
||||||
let q = ''
|
let q = ''
|
||||||
let search
|
let search
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import {onMount} from 'svelte'
|
import {onMount} from 'svelte'
|
||||||
import {nip19} from 'nostr-tools'
|
import {nip19} from 'nostr-tools'
|
||||||
import {fly} from 'svelte/transition'
|
import {fly} from 'svelte/transition'
|
||||||
import {getRelays} from 'src/agent/helpers'
|
import {getEventRelays, getUserRelays} from 'src/agent/helpers'
|
||||||
import network from 'src/agent/network'
|
import network from 'src/agent/network'
|
||||||
import {annotate} from 'src/app'
|
import {annotate} from 'src/app'
|
||||||
import Note from 'src/partials/Note.svelte'
|
import Note from 'src/partials/Note.svelte'
|
||||||
@ -10,7 +10,7 @@
|
|||||||
import Spinner from 'src/partials/Spinner.svelte'
|
import Spinner from 'src/partials/Spinner.svelte'
|
||||||
|
|
||||||
export let note
|
export let note
|
||||||
export let relays = getRelays()
|
export let relays = getUserRelays().concat(getEventRelays(note))
|
||||||
|
|
||||||
let loading = true
|
let loading = true
|
||||||
|
|
||||||
@ -21,6 +21,7 @@
|
|||||||
// Show the main note without waiting for context
|
// Show the main note without waiting for context
|
||||||
if (!note.pubkey) {
|
if (!note.pubkey) {
|
||||||
note = annotate(found, [])
|
note = annotate(found, [])
|
||||||
|
relays = getEventRelays(note)
|
||||||
}
|
}
|
||||||
|
|
||||||
const context = await network.loadContext(relays, found, {
|
const context = await network.loadContext(relays, found, {
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
<script type="ts">
|
<script type="ts">
|
||||||
import Content from 'src/partials/Content.svelte'
|
import Content from 'src/partials/Content.svelte'
|
||||||
import PersonInfo from 'src/partials/PersonInfo.svelte'
|
import PersonInfo from 'src/partials/PersonInfo.svelte'
|
||||||
import {getRelays} from 'src/agent/helpers'
|
import {getUserRelays, getTopRelays} from 'src/agent/helpers'
|
||||||
import database from 'src/agent/database'
|
import database from 'src/agent/database'
|
||||||
import network from 'src/agent/network'
|
import network from 'src/agent/network'
|
||||||
|
|
||||||
export let pubkeys
|
export let pubkeys
|
||||||
|
|
||||||
|
const relays = getUserRelays('read').concat(getTopRelays(pubkeys, 'write'))
|
||||||
const people = database.watch('people', people => people.all({pubkey: pubkeys}))
|
const people = database.watch('people', people => people.all({pubkey: pubkeys}))
|
||||||
|
|
||||||
network.loadPeople(getRelays(), pubkeys)
|
network.loadPeople(relays, pubkeys)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Content gap={2}>
|
<Content gap={2}>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
import Button from "src/partials/Button.svelte"
|
import Button from "src/partials/Button.svelte"
|
||||||
import Content from 'src/partials/Content.svelte'
|
import Content from 'src/partials/Content.svelte'
|
||||||
import SelectButton from "src/partials/SelectButton.svelte"
|
import SelectButton from "src/partials/SelectButton.svelte"
|
||||||
import {user, getWriteRelays} from 'src/agent/helpers'
|
import {user, getUserRelays} from 'src/agent/helpers'
|
||||||
import cmd from 'src/agent/cmd'
|
import cmd from 'src/agent/cmd'
|
||||||
import {modal} from 'src/app'
|
import {modal} from 'src/app'
|
||||||
|
|
||||||
@ -28,7 +28,7 @@
|
|||||||
.concat([["p", $modal.person.pubkey, muffleValue.toString()]])
|
.concat([["p", $modal.person.pubkey, muffleValue.toString()]])
|
||||||
.filter(t => last(t) !== "1")
|
.filter(t => last(t) !== "1")
|
||||||
|
|
||||||
cmd.muffle(getWriteRelays(), muffleTags)
|
cmd.muffle(getUserRelays('write'), muffleTags)
|
||||||
|
|
||||||
history.back()
|
history.back()
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
let search
|
let search
|
||||||
|
|
||||||
database.people.all({'name:!nil': null}).then(people => {
|
database.people.iter({'name:!nil': null}).then(people => {
|
||||||
search = fuzzy(people, {keys: ["name", "about", "pubkey"]})
|
search = fuzzy(people, {keys: ["name", "about", "pubkey"]})
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<script>
|
<script>
|
||||||
import Notes from "src/partials/Notes.svelte"
|
import Notes from "src/partials/Notes.svelte"
|
||||||
import {Cursor, now, batch} from 'src/util/misc'
|
import {Cursor, now, batch} from 'src/util/misc'
|
||||||
import {getRelays, getMuffle} from 'src/agent/helpers'
|
import {getUserRelays, getMuffle} from 'src/agent/helpers'
|
||||||
import network from 'src/agent/network'
|
import network from 'src/agent/network'
|
||||||
import {threadify} from 'src/app'
|
import {threadify} from 'src/app'
|
||||||
|
|
||||||
const relays = getRelays()
|
const relays = getUserRelays('read')
|
||||||
const filter = {kinds: [1, 5, 7]}
|
const filter = {kinds: [1, 5, 7]}
|
||||||
const cursor = new Cursor()
|
const cursor = new Cursor()
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<script>
|
<script>
|
||||||
import {uniqBy, prop} from 'ramda'
|
import {uniq} from 'ramda'
|
||||||
import Notes from "src/partials/Notes.svelte"
|
import Notes from "src/partials/Notes.svelte"
|
||||||
import {now, Cursor, shuffle, batch} from 'src/util/misc'
|
import {now, Cursor, shuffle, batch} from 'src/util/misc'
|
||||||
import {user, getRelays, getFollows, getMuffle} from 'src/agent/helpers'
|
import {user, getTopRelays, getFollows, getMuffle} from 'src/agent/helpers'
|
||||||
import network from 'src/agent/network'
|
import network from 'src/agent/network'
|
||||||
import {threadify} from 'src/app'
|
import {threadify} from 'src/app'
|
||||||
|
|
||||||
@ -10,20 +10,23 @@
|
|||||||
// sending too many pubkeys. This will also result in some variety.
|
// sending too many pubkeys. This will also result in some variety.
|
||||||
const follows = shuffle(getFollows($user?.pubkey))
|
const follows = shuffle(getFollows($user?.pubkey))
|
||||||
const others = shuffle(follows.flatMap(getFollows)).slice(0, 50)
|
const others = shuffle(follows.flatMap(getFollows)).slice(0, 50)
|
||||||
const authors = follows.concat(others).slice(0, 100)
|
const authors = uniq(follows.concat(others)).slice(0, 100)
|
||||||
const filter = {kinds: [1, 7], authors}
|
const filter = {kinds: [1, 7], authors}
|
||||||
const cursor = new Cursor()
|
const cursor = new Cursor()
|
||||||
const relays = uniqBy(prop('url'), follows.flatMap(getRelays))
|
|
||||||
|
|
||||||
const listenForNotes = onNotes =>
|
const listenForNotes = async onNotes => {
|
||||||
network.listen(relays, {...filter, since: now()}, batch(300, async notes => {
|
const relays = getTopRelays(authors, 'write')
|
||||||
|
|
||||||
|
return network.listen(relays, {...filter, since: now()}, batch(300, async notes => {
|
||||||
const context = await network.loadContext(relays, notes)
|
const context = await network.loadContext(relays, notes)
|
||||||
|
|
||||||
onNotes(threadify(notes, context, {muffle: getMuffle(), showReplies: false}))
|
onNotes(threadify(notes, context, {muffle: getMuffle(), showReplies: false}))
|
||||||
}))
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
const loadNotes = async () => {
|
const loadNotes = async () => {
|
||||||
const {limit, until} = cursor
|
const {limit, until} = cursor
|
||||||
|
const relays = getTopRelays(authors, 'write')
|
||||||
const notes = await network.load(relays, {...filter, limit, until})
|
const notes = await network.load(relays, {...filter, limit, until})
|
||||||
const context = await network.loadContext(relays, notes)
|
const context = await network.loadContext(relays, notes)
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
<script>
|
<script>
|
||||||
import Notes from "src/partials/Notes.svelte"
|
import Notes from "src/partials/Notes.svelte"
|
||||||
import {now, batch, Cursor} from 'src/util/misc'
|
import {now, batch, Cursor} from 'src/util/misc'
|
||||||
import {getRelays, getMuffle} from 'src/agent/helpers'
|
import {getPubkeyRelays, getMuffle} from 'src/agent/helpers'
|
||||||
import network from 'src/agent/network'
|
import network from 'src/agent/network'
|
||||||
import {threadify} from 'src/app'
|
import {threadify} from 'src/app'
|
||||||
|
|
||||||
export let pubkey
|
export let pubkey
|
||||||
|
|
||||||
const relays = getRelays(pubkey)
|
const relays = getPubkeyRelays(pubkey, 'write')
|
||||||
const filter = {kinds: [7], authors: [pubkey]}
|
const filter = {kinds: [7], authors: [pubkey]}
|
||||||
const cursor = new Cursor()
|
const cursor = new Cursor()
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
<script>
|
<script>
|
||||||
import Notes from "src/partials/Notes.svelte"
|
import Notes from "src/partials/Notes.svelte"
|
||||||
import {now, batch, Cursor} from 'src/util/misc'
|
import {now, batch, Cursor} from 'src/util/misc'
|
||||||
import {getRelays, getMuffle} from 'src/agent/helpers'
|
import {getPubkeyRelays, getMuffle} from 'src/agent/helpers'
|
||||||
import network from 'src/agent/network'
|
import network from 'src/agent/network'
|
||||||
import {threadify} from 'src/app'
|
import {threadify} from 'src/app'
|
||||||
|
|
||||||
export let pubkey
|
export let pubkey
|
||||||
|
|
||||||
const relays = getRelays(pubkey)
|
const relays = getPubkeyRelays(pubkey, 'write')
|
||||||
const filter = {kinds: [1], authors: [pubkey]}
|
const filter = {kinds: [1], authors: [pubkey]}
|
||||||
const cursor = new Cursor()
|
const cursor = new Cursor()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user