From 7dbb69e54ae8dd5a4d1e8b8e342b8ab41f6e4676 Mon Sep 17 00:00:00 2001 From: Jonathan Staab Date: Wed, 15 Feb 2023 15:22:06 -0600 Subject: [PATCH] Upgrade nostr tools, fix initial user/network loading, fix unnecessary dm alerts --- CHANGELOG.md | 2 ++ ROADMAP.md | 4 ++-- package-lock.json | Bin 385966 -> 386739 bytes package.json | 2 +- src/App.svelte | 7 +++---- src/agent/database.ts | 11 ++++++++++- src/agent/helpers.ts | 7 ++----- src/agent/network.ts | 11 ++--------- src/agent/pool.ts | 27 +++++++++++++++++++++++++-- src/app/index.ts | 5 +++-- src/app/messages.js | 8 ++++---- src/partials/RelayCard.svelte | 2 -- src/views/notes/Network.svelte | 5 +++-- src/views/notes/Popular.svelte | 6 +++--- src/views/notes/Top.svelte | 6 +++--- 15 files changed, 63 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f0e3fb4..3ecd0e68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ - [x] Show relay status based on stats not current connection status - [x] Auto-mention person when creating a note from their profile page - [x] Make chat header overlap main header to save space +- [x] Strip formatting when pasting into Compose +- [x] Upgraded nostr-tools to 1.4.1 ## 0.2.11 diff --git a/ROADMAP.md b/ROADMAP.md index 34bfa254..629176a4 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -9,10 +9,10 @@ - [ ] Fix anon/new user experience - [ ] Initial user load doesn't have any relays, cache user or wait for people db to be loaded - [ ] Fix bugs on bugsnag -- [ ] Fix bugs on github # Snacks +- [ ] Relay recommendations based on follows/followers - [ ] Pinned posts ala snort - [ ] Likes list on note detail. Maybe a sidebar or header for note detail page? - [ ] Support key delegation @@ -54,7 +54,7 @@ # Maintenance -- [ ] If the latest message in a dm was the user, don't show notification +- [ ] Don't waste space caching rooms, load those lazily - [ ] Normalize relay urls (lowercase, strip trailing slash) - [ ] Use nip 56 for reporting - https://github.com/nostr-protocol/nips/pull/205#issuecomment-1419234230 diff --git a/package-lock.json b/package-lock.json index 3f1faf18c2b2ecc9ba5a05614236f5fa7d994157..e5b08a894d5a76b5adea46bcf27ad5e63af47383 100644 GIT binary patch delta 1198 zcmciA&1=(e7zc2gba>dN9VmP2bY0u+P}-zP(-&p3WL?*;FR|T{v_;(dlJq6bnkHRe z=BWw}1VPN<2YQ%O^dvIbp%;hX#nWJ({0F><2zvA&x(W577lnCy9v;3t4?LgeZ-(~{ zhIg++fZx)c*}DxH&ueqI9_&7YFb#>0f+u%%))jx6&DK+HOw8e;NY$gkT63NjlFABF zT(8oJHbE`9Y(d5uN)Wyz8sJ<3A29JT)UY(gK(v0XP+f+cRu}Z@u5**n?BC@*KVzXsmVKL@fN{FE( zfeHBlS#~m{+Zj$uX@8@}E=V?+Zu2?ZCWQDjg<_FZ29Y_MR5be4E#TOK#-@(UsdKW;=kP#$|kd=`GWR{K96H$R9@*6ou5>Wv|L+OSqT^0!2dWu# zR-F?>I`BAHus}090!S9f1ePq&pg~sndcDLeQx_+vu3-)@aQa{?IGlm{yZaXCWn6ze z2AyKxxX!D6xr`6@0*D>ymG+~YmU(Ys8=+-aqLRY`u_8*fmqnZt^X`_^Y*A=Hrq}Zv zA(Yf85%d<-^m2>ASdOKLc`hV|%3MPUmP5ssh!yax5DiDYp3T^blFsLwV093l80jrL zJ~UfexA%Im^9VYp9qyaJ01ur8SEpg`P;d6@LhaKHd$-wuE`9i&Tk0gZ)e5t-Q=qd7 zp9Q`SJfJ-^jr>6#dm{3h;A;*xZf$4a?si5Wz5jpA?a;6V7&@@wAJL6=?|sux&i#$I Q)X8`|`ds(%Y+wJ=AI&b09{>OV delta 820 zcmci9Pixa)0Dy7wrrkjX>cz^ebt9b$!6j|lW<|uc3A{=F#AZpCwg)lEwzg}UjwUsk zp2WjY5D%~Tf<1ZgD#{M|2s;h+Bg~74%!6LVsUJW*x#M$vetQRr*ZYY#_W}OYAy4l; z2FVo3F6HstDZwG8o{0aBr6PV{5|r*J8MRkfUlyBixT$c3)~aVIjA28$q4+xN4T5ap zt|6~8q9e%AYga0xk+1s=*zM^x+hs~-s}W{Z*5Yi_9tSOxzqN)l5lEpY3p4_K4zcwa z{Lv!k@V7jm)&`bo2T=1QM$ktSpY6CEBXo^Snck8Ze#{u9Qngn0$Ey{F7Mc?8bcgCa zhlBc9otT^ktA?V9o>p*%Tdue*SMp-GV+Q!c4R8*WxHL@%8=a@ z9Zm@8P^-BULAP>lr>~ff>9@U7-l6$?CQ$n#EO9g@zJsgyD+SKX-2U^I$A>>-i|9~F zVlfS_U^xxW6Gim&*|q3h8tkjlAOywFe{*U650?PD7J2>TP`+%CNu27Er*@|{8BOh& f@Zv-y)ZI9R?$ply17ab1c^sQxiK3PGk5|6{H8u~N diff --git a/package.json b/package.json index 93126b0b..c6bd7b3e 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "husky": "^8.0.3", "localforage": "^1.10.0", "localforage-memoryStorageDriver": "^0.9.2", - "nostr-tools": "^1.2.1", + "nostr-tools": "^1.4.1", "npm-run-all": "^4.1.5", "qr-scanner": "^1.4.2", "qrcode": "^1.5.1", diff --git a/src/App.svelte b/src/App.svelte index 5a17fdef..67c36600 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -3,7 +3,6 @@ import "@fortawesome/fontawesome-free/css/solid.css" import {find, is, identity, nthArg, pluck} from 'ramda' - import {onMount} from "svelte" import {createMap, first} from 'hurdak/lib/hurdak' import {writable, get} from "svelte/store" import {fly, fade} from "svelte/transition" @@ -88,13 +87,12 @@ )) } - onMount(() => { + database.onReady(() => { if ($user) { loadAppData($user.pubkey) } // Background work - const interval = setInterval(() => { alertSlowConnections() retrieveRelayMeta() @@ -168,6 +166,7 @@ } }) + // Log usage on navigate const unsubHistory = globalHistory.listen(({location}) => { if (!location.hash) { // Remove identifying information, e.g. pubkeys, event ids, etc @@ -178,8 +177,8 @@ } }) + // Keep scroll position on body, but don't allow scrolling const unsubModal = modal.subscribe($modal => { - // Keep scroll position on body, but don't allow scrolling if ($modal) { logUsage(btoa(['modal', $modal.type].join(':'))) diff --git a/src/agent/database.ts b/src/agent/database.ts index 7333411c..58e74f1b 100644 --- a/src/agent/database.ts +++ b/src/agent/database.ts @@ -304,8 +304,17 @@ const clearAll = () => Promise.all(Object.keys(registry).map(clear)) const ready = derived(pluck('ready', Object.values(registry)), all(identity)) +const onReady = cb => { + const unsub = ready.subscribe($ready => { + if ($ready) { + cb() + unsub() + } + }) +} + export default { getItem, setItem, setItems, removeItem, removeItems, length, clear, keys, dump, iterate, watch, getPersonWithFallback, clearAll, people, rooms, messages, - alerts, relays, routes, ready, + alerts, relays, routes, ready, onReady, } diff --git a/src/agent/helpers.ts b/src/agent/helpers.ts index c0b66f94..214fc0ee 100644 --- a/src/agent/helpers.ts +++ b/src/agent/helpers.ts @@ -32,11 +32,8 @@ export const getMuffle = () => { return Tags.wrap($user.muffle.filter(shouldMuffle)).values().all() } -export const getFollows = pubkey => { - const person = database.getPersonWithFallback(pubkey) - - return Tags.wrap(person.petnames || defaults.petnames).values().all() -} +export const getFollows = pubkey => + database.getPersonWithFallback(pubkey).petnames || defaults.petnames export const getPersonRelays = (person, mode = 'all') => { const relays = isEmpty(person?.relays || []) ? defaults.relays : person.relays diff --git a/src/agent/network.ts b/src/agent/network.ts index 2b445ac3..b1b705c4 100644 --- a/src/agent/network.ts +++ b/src/agent/network.ts @@ -2,7 +2,7 @@ import {uniq, uniqBy, prop, map, propEq, indexBy, pluck} from 'ramda' import {findReply, personKinds, findReplyId, Tags} from 'src/util/nostr' import {chunk} from 'hurdak/lib/hurdak' import {batch} from 'src/util/misc' -import {getFollows, getStalePubkeys, getTopEventRelays} from 'src/agent/helpers' +import {getStalePubkeys, getTopEventRelays} from 'src/agent/helpers' import pool from 'src/agent/pool' import keys from 'src/agent/keys' import sync from 'src/agent/sync' @@ -70,13 +70,6 @@ const loadPeople = (relays, pubkeys, {kinds = personKinds, force = false, ...opt : Promise.resolve([]) } -const loadNetwork = async (relays, pubkey) => { - const tags = Tags.wrap(getFollows(pubkey)) - - // Use nip-2 recommended relays to load our user's second-order follows - await loadPeople(tags.relays(), tags.values().all()) -} - const loadParents = (relays, notes) => { const parentIds = new Set(Tags.wrap(notes.map(findReply)).values().all()) @@ -128,7 +121,7 @@ const streamContext = ({relays, notes, updateNotes, depth = 0}) => { } export default { - publish, load, listen, listenUntilEose, loadNetwork, loadPeople, personKinds, + publish, load, listen, listenUntilEose, loadPeople, personKinds, loadParents, streamContext, } diff --git a/src/agent/pool.ts b/src/agent/pool.ts index f81d8e77..73bdde88 100644 --- a/src/agent/pool.ts +++ b/src/agent/pool.ts @@ -3,7 +3,7 @@ import type {MyEvent} from 'src/util/types' import {relayInit} from 'nostr-tools' import {uniqBy, without, prop, find, is} from 'ramda' import {ensurePlural} from 'hurdak/lib/hurdak' -import {warn, log} from 'src/util/logger' +import {warn, log, error} from 'src/util/logger' import {isRelay} from 'src/util/nostr' import {sleep} from 'src/util/misc' import database from 'src/agent/database' @@ -51,6 +51,14 @@ class Connection { if (shouldConnect) { this.status = CONNECTION_STATUS.PENDING this.promise = this.nostr.connect() + + this.nostr.on('connect', () => { + this.status = CONNECTION_STATUS.READY + }) + + this.nostr.on('error', () => { + this.status = CONNECTION_STATUS.ERROR + }) } if (this.status === CONNECTION_STATUS.PENDING) { @@ -170,7 +178,11 @@ const subscribe = async (relays, filters, {onEvent, onEose}: Record { @@ -220,7 +232,10 @@ const subscribe = async (relays, filters, {onEvent, onEose}: Record active, unsub: () => { log(`Closing subscription ${id}`) @@ -232,6 +247,7 @@ const subscribe = async (relays, filters, {onEvent, onEose}: Record { + // If we've already unsubscribed we're good + if (!agg.isActive()) { + return + } + const isComplete = eose.size === relays.length const isTimeout = Date.now() - now >= timeout diff --git a/src/app/index.ts b/src/app/index.ts index df5bdfab..f0670534 100644 --- a/src/app/index.ts +++ b/src/app/index.ts @@ -5,7 +5,7 @@ import {createMap, ellipsize} from 'hurdak/lib/hurdak' import {get} from 'svelte/store' import {renderContent} from 'src/util/html' import {Tags, displayPerson, findReplyId} from 'src/util/nostr' -import {user, getUserRelays} from 'src/agent/helpers' +import {user, getUserRelays, getFollows} from 'src/agent/helpers' import defaults from 'src/agent/defaults' import database from 'src/agent/database' import network from 'src/agent/network' @@ -19,12 +19,13 @@ export {toast, modal, settings, alerts, messages, logUsage} export const loadAppData = pubkey => { const relays = getUserRelays('read') + const follows = Tags.wrap(getFollows(pubkey)) return Promise.all([ - network.loadNetwork(relays, pubkey), alerts.load(relays, pubkey), alerts.listen(relays, pubkey), messages.listen(relays, pubkey), + network.loadPeople(follows.relays(), follows.values().all()), ]) } diff --git a/src/app/messages.js b/src/app/messages.js index 1553a4e7..d35bdf2d 100644 --- a/src/app/messages.js +++ b/src/app/messages.js @@ -30,10 +30,10 @@ const listen = async (relays, pubkey) => { await network.loadPeople(relays, pluck('pubkey', messages)) mostRecentByPubkey.update(o => { - for (const {pubkey, recipient, created_at} of messages) { - const k = pubkey === $user.pubkey ? recipient : pubkey - - o[k] = Math.max(created_at, o[k] || 0) + for (const {pubkey, created_at} of messages) { + if (pubkey !== $user.pubkey) { + o[pubkey] = Math.max(created_at, o[pubkey] || 0) + } } return o diff --git a/src/partials/RelayCard.svelte b/src/partials/RelayCard.svelte index f7d42040..cf41de24 100644 --- a/src/partials/RelayCard.svelte +++ b/src/partials/RelayCard.svelte @@ -31,8 +31,6 @@ quality = null message = "Not connected" } - - console.log(quality, message) }) }) diff --git a/src/views/notes/Network.svelte b/src/views/notes/Network.svelte index bc894dad..bfade329 100644 --- a/src/views/notes/Network.svelte +++ b/src/views/notes/Network.svelte @@ -2,12 +2,13 @@ import {uniq} from 'ramda' import Notes from "src/partials/Notes.svelte" import {shuffle} from 'src/util/misc' + import {Tags} from 'src/util/nostr' import {user, getTopRelays, getFollows} from 'src/agent/helpers' // Get first- and second-order follows. shuffle and slice network so we're not // sending too many pubkeys. This will also result in some variety. - const follows = shuffle(getFollows($user?.pubkey)) - const others = shuffle(follows.flatMap(getFollows)).slice(0, 50) + const follows = shuffle(Tags.wrap(getFollows($user?.pubkey)).values().all()) + const others = shuffle(Tags.wrap(follows.flatMap(getFollows)).values().all()).slice(0, 50) const authors = uniq(follows.concat(others)).slice(0, 100) const relays = getTopRelays(authors, 'write') const filter = {kinds: [1, 7], authors} diff --git a/src/views/notes/Popular.svelte b/src/views/notes/Popular.svelte index 21d0cc27..5ee6b159 100644 --- a/src/views/notes/Popular.svelte +++ b/src/views/notes/Popular.svelte @@ -2,13 +2,13 @@ import {uniq} from 'ramda' import Notes from "src/partials/Notes.svelte" import {shuffle} from 'src/util/misc' - import {isLike} from 'src/util/nostr' + import {isLike, Tags} from 'src/util/nostr' import {user, getTopRelays, getFollows} from 'src/agent/helpers' // Get first- and second-order follows. shuffle and slice network so we're not // sending too many pubkeys. This will also result in some variety. - const follows = shuffle(getFollows($user?.pubkey)) - const others = shuffle(follows.flatMap(getFollows)).slice(0, 50) + const follows = shuffle(Tags.wrap(getFollows($user?.pubkey)).values().all()) + const others = shuffle(Tags.wrap(follows.flatMap(getFollows)).values().all()).slice(0, 50) const authors = uniq(follows.concat(others)).slice(0, 100) const relays = getTopRelays(authors, 'write') const filter = {kinds: [1, 7], authors} diff --git a/src/views/notes/Top.svelte b/src/views/notes/Top.svelte index 21d0cc27..5ee6b159 100644 --- a/src/views/notes/Top.svelte +++ b/src/views/notes/Top.svelte @@ -2,13 +2,13 @@ import {uniq} from 'ramda' import Notes from "src/partials/Notes.svelte" import {shuffle} from 'src/util/misc' - import {isLike} from 'src/util/nostr' + import {isLike, Tags} from 'src/util/nostr' import {user, getTopRelays, getFollows} from 'src/agent/helpers' // Get first- and second-order follows. shuffle and slice network so we're not // sending too many pubkeys. This will also result in some variety. - const follows = shuffle(getFollows($user?.pubkey)) - const others = shuffle(follows.flatMap(getFollows)).slice(0, 50) + const follows = shuffle(Tags.wrap(getFollows($user?.pubkey)).values().all()) + const others = shuffle(Tags.wrap(follows.flatMap(getFollows)).values().all()).slice(0, 50) const authors = uniq(follows.concat(others)).slice(0, 100) const relays = getTopRelays(authors, 'write') const filter = {kinds: [1, 7], authors}