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 *.njsproj
*.sln *.sln
*.sw? *.sw?
ssl

View File

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

View File

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

View File

@ -6,14 +6,13 @@
import Input from "src/partials/Input.svelte" import Input from "src/partials/Input.svelte"
import Anchor from "src/partials/Anchor.svelte" import Anchor from "src/partials/Anchor.svelte"
import {user} from "src/state/user" import {user} from "src/state/user"
import {logout} from "src/state/app"
import toast from "src/state/toast" import toast from "src/state/toast"
const keypairUrl = 'https://www.cloudflare.com/learning/ssl/how-does-public-key-encryption-work/' 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 delegationUrl = 'https://github.com/nostr-protocol/nips/blob/b62aa418dee13aac1899ea7c6946a0f55dd7ee84/26.md'
const copyKey = type => { 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.`) 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. using <Anchor external href={delegationUrl}>delegation keys</Anchor> instead.
</p> </p>
</div> </div>
<Anchor class="block text-right" on:click={logout}>Log Out</Anchor>
</div> </div>
</div> </div>
</div> </div>

View File

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

View File

@ -32,21 +32,18 @@ export const logout = () => {
// Utils // Utils
export const ensureAccounts = async pubkeys => { export const ensureAccounts = async (pubkeys, {force = false} = {}) => {
const $accounts = get(accounts) const $accounts = get(accounts)
// Don't request accounts we recently updated // Don't request accounts we recently updated
pubkeys = pubkeys.filter( 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) { if (pubkeys.length) {
return
}
const events = await channels.getter.all({kinds: [0], authors: pubkeys}) const events = await channels.getter.all({kinds: [0], authors: pubkeys})
accounts.update($accounts => { await accounts.update($accounts => {
events.forEach(e => { events.forEach(e => {
$accounts[e.pubkey] = { $accounts[e.pubkey] = {
pubkey: e.pubkey, pubkey: e.pubkey,
@ -60,6 +57,10 @@ export const ensureAccounts = async pubkeys => {
}) })
} }
// Keep our user in sync
user.update($user => ({...$user, ...get(accounts)[$user.pubkey]}))
}
export const findNotes = (filters, cb) => { export const findNotes = (filters, cb) => {
const start = () => { const start = () => {
const notes = writable([]) const notes = writable([])

View File

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

View File

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