Load account during initial setup

This commit is contained in:
Jonathan Staab 2022-11-26 21:38:25 -08:00
parent 97b8e080ec
commit e6b0cc78fd
8 changed files with 48 additions and 37 deletions

1
.gitignore vendored
View File

@ -22,3 +22,4 @@ dist-ssr
*.njsproj
*.sln
*.sw?
ssl

View File

@ -1,5 +1,6 @@
Bugs
- [ ] Pagination
- [ ] Memoize room list, currently every time the user switches chat rooms it pulls the full list
- [ ] Fix toast, it gets in the way. Make it smaller and dismissable.

View File

@ -2,7 +2,9 @@
import {fly} from 'svelte/transition'
import {registerRelay} from 'src/state/nostr'
import toast from 'src/state/toast'
import {modal} from 'src/state/app'
import {user} from 'src/state/user'
import {modal, ensureAccounts} from 'src/state/app'
import {dispatch} from 'src/state/dispatch'
import Input from 'src/partials/Input.svelte'
import Button from 'src/partials/Button.svelte'
@ -16,7 +18,12 @@
}
registerRelay(url)
dispatch("relay/join", url)
modal.set(null)
if ($user) {
ensureAccounts([$user.pubkey], {force: true})
}
}
</script>
@ -28,7 +35,7 @@
<div class="flex flex-col gap-8 w-full">
<div class="flex flex-col gap-1">
<strong>Relay URL</strong>
<Input bind:value={url}>
<Input autofocus bind:value={url}>
<i slot="before" class="fa-solid fa-link" />
</Input>
<p class="text-sm text-light">

View File

@ -6,14 +6,13 @@
import Input from "src/partials/Input.svelte"
import Anchor from "src/partials/Anchor.svelte"
import {user} from "src/state/user"
import {logout} from "src/state/app"
import toast from "src/state/toast"
const keypairUrl = 'https://www.cloudflare.com/learning/ssl/how-does-public-key-encryption-work/'
const delegationUrl = 'https://github.com/nostr-protocol/nips/blob/b62aa418dee13aac1899ea7c6946a0f55dd7ee84/26.md'
const copyKey = type => {
copyToClipboard(type === 'private' ? $user.privKey : $user.pubkey)
copyToClipboard(type === 'private' ? $user.privkey : $user.pubkey)
toast.show("info", `Your ${type} key has been copied to the clipboard.`)
}
@ -58,7 +57,6 @@
using <Anchor external href={delegationUrl}>delegation keys</Anchor> instead.
</p>
</div>
<Anchor class="block text-right" on:click={logout}>Log Out</Anchor>
</div>
</div>
</div>

View File

@ -4,17 +4,17 @@
import Input from "src/partials/Input.svelte"
import Anchor from "src/partials/Anchor.svelte"
import {dispatch} from "src/state/dispatch"
import {modal} from "src/state/app"
import {relays, knownRelays} from "src/state/nostr"
import {modal} from "src/state/app"
let q = ""
let search
$: search = fuzzy($knownRelays || [], {keys: ["name", "description", "url"]})
const toggle = (url, value) => {
dispatch(value ? "relay/join" : "relay/leave", url)
}
const join = url => dispatch("relay/join", url)
const leave = url => dispatch("relay/leave", url)
</script>
<div class="flex justify-center py-8 px-4" in:fly={{y: 20}}>
@ -41,7 +41,7 @@
</div>
<a
class="underline cursor-pointer"
on:click={() => toggle(relay.url, !$relays.includes(relay.url))}>
on:click={() => $relays.includes(relay.url) ? leave(relay.url) : join(relay.url)}>
{$relays.includes(relay.url) ? "Leave" : "Join"}
</a>
</div>

View File

@ -32,32 +32,33 @@ export const logout = () => {
// Utils
export const ensureAccounts = async pubkeys => {
export const ensureAccounts = async (pubkeys, {force = false} = {}) => {
const $accounts = get(accounts)
// Don't request accounts we recently updated
pubkeys = pubkeys.filter(
k => !$accounts[k] || $accounts[k].refreshed < now() - timedelta(10, 'minutes')
k => force || !$accounts[k] || $accounts[k].refreshed < now() - timedelta(10, 'minutes')
)
if (!pubkeys.length) {
return
if (pubkeys.length) {
const events = await channels.getter.all({kinds: [0], authors: pubkeys})
await accounts.update($accounts => {
events.forEach(e => {
$accounts[e.pubkey] = {
pubkey: e.pubkey,
...$accounts[e.pubkey],
...JSON.parse(e.content),
refreshed: now(),
}
})
return $accounts
})
}
const events = await channels.getter.all({kinds: [0], authors: pubkeys})
accounts.update($accounts => {
events.forEach(e => {
$accounts[e.pubkey] = {
pubkey: e.pubkey,
...$accounts[e.pubkey],
...JSON.parse(e.content),
refreshed: now(),
}
})
return $accounts
})
// Keep our user in sync
user.update($user => ({...$user, ...get(accounts)[$user.pubkey]}))
}
export const findNotes = (filters, cb) => {

View File

@ -3,7 +3,8 @@ import {getPublicKey} from 'nostr-tools'
import {get} from 'svelte/store'
import {first, defmulti} from "hurdak/lib/hurdak"
import {user} from "src/state/user"
import {nostr, channels, relays} from 'src/state/nostr'
import {nostr, relays} from 'src/state/nostr'
import {ensureAccounts} from 'src/state/app'
// Commands are processed in two layers:
// - App-oriented commands are created via dispatch
@ -19,11 +20,11 @@ dispatch.addMethod("account/init", async (topic, privkey) => {
// Set what we know about the user to our store
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: [pubkey]}))
// Make sure we have data for this user
await ensureAccounts([pubkey], {force: true})
// Tell the caller whether this user was found
return {found}
return {found: Boolean(get(user).name)}
})
dispatch.addMethod("account/update", async (topic, updates) => {
@ -34,8 +35,14 @@ dispatch.addMethod("account/update", async (topic, updates) => {
await nostr.publish(nostr.event(0, JSON.stringify(updates)))
})
dispatch.addMethod("relay/join", (topic, url) => {
dispatch.addMethod("relay/join", async (topic, url) => {
const $user = get(user)
relays.update(r => r.concat(url))
if ($user) {
await ensureAccounts([$user.pubkey], {force: true})
}
})
dispatch.addMethod("relay/leave", (topic, url) => {

View File

@ -3,11 +3,7 @@ import { defineConfig } from 'vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'
import { nodePolyfills } from 'vite-plugin-node-polyfills'
// https://vitejs.dev/config/
export default defineConfig({
define: {
global: {},
},
resolve: {
alias: {
src: path.resolve(__dirname, 'src'),