Add keys page

This commit is contained in:
Jonathan Staab 2022-11-24 20:14:51 -08:00
parent 20f8d52c78
commit b40515b133
7 changed files with 100 additions and 19 deletions

View File

@ -11,6 +11,7 @@
import Feed from "src/routes/Feed.svelte" import Feed from "src/routes/Feed.svelte"
import Login from "src/routes/Login.svelte" import Login from "src/routes/Login.svelte"
import Profile from "src/routes/Profile.svelte" import Profile from "src/routes/Profile.svelte"
import Keys from "src/routes/Keys.svelte"
import RelayList from "src/routes/RelayList.svelte" import RelayList from "src/routes/RelayList.svelte"
import UserDetail from "src/routes/UserDetail.svelte" import UserDetail from "src/routes/UserDetail.svelte"
import NoteCreate from "src/routes/NoteCreate.svelte" import NoteCreate from "src/routes/NoteCreate.svelte"
@ -53,9 +54,14 @@
<Route path="/notes/new" component={NoteCreate} /> <Route path="/notes/new" component={NoteCreate} />
<Route path="/chat" component={Chat} /> <Route path="/chat" component={Chat} />
<Route path="/chat/new" component={ChatEdit} /> <Route path="/chat/new" component={ChatEdit} />
<Route path="/chat/:room" component={ChatRoom} /> <Route path="/chat/:room" let:params>
{#key params.room}
<ChatRoom room={params.room} />
{/key}
</Route>
<Route path="/chat/:room/edit" component={ChatEdit} /> <Route path="/chat/:room/edit" component={ChatEdit} />
<Route path="/user/:pubkey" component={UserDetail} /> <Route path="/user/:pubkey" component={UserDetail} />
<Route path="/settings/keys" component={Keys} />
<Route path="/settings/relays" component={RelayList} /> <Route path="/settings/relays" component={RelayList} />
<Route path="/settings/profile" component={Profile} /> <Route path="/settings/profile" component={Profile} />
<Route path="/login" component={Login} /> <Route path="/login" component={Login} />
@ -67,11 +73,13 @@
class:-ml-56={!$menuIsOpen} class:-ml-56={!$menuIsOpen}
> >
{#if $user} {#if $user}
<li class="flex gap-2 px-4 py-2 pb-8 items-center"> <li>
<a href={`/user/${$user.pubkey}`} class="flex gap-2 px-4 py-2 pb-6 items-center">
<div <div
class="overflow-hidden w-6 h-6 rounded-full bg-cover bg-center shrink-0 border border-solid border-white" class="overflow-hidden w-6 h-6 rounded-full bg-cover bg-center shrink-0 border border-solid border-white"
style="background-image: url({$user.picture})" /> style="background-image: url({$user.picture})" />
<span class="text-lg font-bold">{$user.name}</span> <span class="text-lg font-bold">{$user.name}</span>
</a>
</li> </li>
{/if} {/if}
<li class="cursor-pointer"> <li class="cursor-pointer">
@ -87,8 +95,8 @@
<li class="h-px mx-3 my-4 bg-medium" /> <li class="h-px mx-3 my-4 bg-medium" />
{#if $user} {#if $user}
<li class="cursor-pointer"> <li class="cursor-pointer">
<a class="block px-4 py-2 hover:bg-accent transition-all" href="/user/{$user.pubkey}"> <a class="block px-4 py-2 hover:bg-accent transition-all" href="/settings/keys">
<i class="fa-solid fa-user-astronaut mr-2" /> Profile <i class="fa-solid fa-key mr-2" /> Keys
</a> </a>
</li> </li>
<li class="cursor-pointer"> <li class="cursor-pointer">

View File

@ -2,6 +2,7 @@
import cx from "classnames" import cx from "classnames"
import {switcher} from "hurdak/lib/hurdak" import {switcher} from "hurdak/lib/hurdak"
export let external = false
export let type = "anchor" export let type = "anchor"
export let href export let href
@ -15,4 +16,6 @@
) )
</script> </script>
<a on:click {...$$props} {href} class={className}><slot /></a> <a on:click {...$$props} {href} class={className} target={external && '_blank noopener'}>
<slot />
</a>

View File

@ -14,10 +14,8 @@
const createRoom = () => navigate(`/chat/new`) const createRoom = () => navigate(`/chat/new`)
// TODO hack: there should be a way to re-render a route when the url changes
const setRoom = id => { const setRoom = id => {
navigate(`/chat`) navigate(`/chat/${id}`)
setTimeout(() => navigate(`/chat/${id}`))
} }
onMount(() => { onMount(() => {

View File

@ -146,19 +146,19 @@
</div> </div>
</div> </div>
{/if} {/if}
<div class="fixed bottom-0 w-full -ml-56 pl-56 flex bg-light border-medium border-t border-solid border-dark"> <div class="fixed bottom-0 w-full -ml-56 pl-56 flex bg-medium border-medium border-t border-solid border-dark">
<textarea <textarea
rows="4" rows="4"
autofocus autofocus
placeholder="Type something..." placeholder="Type something..."
bind:this={textarea} bind:this={textarea}
on:keypress={onKeyPress} on:keypress={onKeyPress}
class="w-full p-2 text-black bg-light class="w-full p-2 text-white bg-medium
placeholder:text-medium outline-0 resize-none" /> placeholder:text-light outline-0 resize-none" />
<div <div
on:click={sendMessage} on:click={sendMessage}
class="flex flex-col py-8 p-4 justify-center gap-2 border-l border-solid border-dark class="flex flex-col py-8 p-4 justify-center gap-2 border-l border-solid border-dark
hover:bg-accent transition-all cursor-pointer text-black "> hover:bg-accent transition-all cursor-pointer text-white ">
<i class="fa-solid fa-paper-plane fa-xl" /> <i class="fa-solid fa-paper-plane fa-xl" />
</div> </div>
</div> </div>

View File

@ -48,6 +48,7 @@
filter: {kinds: [0], authors: [e.pubkey]}, filter: {kinds: [0], authors: [e.pubkey]},
cb: e => { cb: e => {
$accounts[e.pubkey] = { $accounts[e.pubkey] = {
pubkey: e.pubkey,
...$accounts[e.pubkey], ...$accounts[e.pubkey],
...JSON.parse(e.content), ...JSON.parse(e.content),
} }
@ -67,12 +68,12 @@
{#each annotatedNotes as n} {#each annotatedNotes as n}
<li in:fly={{y: 20}} class="py-1 chat-message"> <li in:fly={{y: 20}} class="py-1 chat-message">
{#if n.showAccount} {#if n.showAccount}
<div class="flex gap-2 items-center mt-2"> <a href={`/user/${n.account.pubkey}`} class="flex gap-2 items-center mt-2">
<div <div
class="overflow-hidden w-4 h-4 rounded-full bg-cover bg-center shrink-0 border border-solid border-white" class="overflow-hidden w-4 h-4 rounded-full bg-cover bg-center shrink-0 border border-solid border-white"
style="background-image: url({n.account.picture})" /> style="background-image: url({n.account.picture})" />
<span class="text-lg font-bold">{n.account.name}</span> <span class="text-lg font-bold">{n.account.name}</span>
</div> </a>
{/if} {/if}
<div class="ml-6">{n.content}</div> <div class="ml-6">{n.content}</div>
</li> </li>

71
src/routes/Keys.svelte Normal file
View File

@ -0,0 +1,71 @@
<script>
import {onMount} from "svelte"
import {fly} from 'svelte/transition'
import {navigate} from "svelte-routing"
import {copyToClipboard} from "src/util/html"
import Input from "src/partials/Input.svelte"
import Select from "src/partials/Select.svelte"
import Anchor from "src/partials/Anchor.svelte"
import Button from "src/partials/Button.svelte"
import {user} from "src/state/user"
import {dispatch} from "src/state/dispatch"
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)
toast.show("info", `Your ${type} key has been copied to the clipboard.`)
}
const logout = () => {
user.set(null)
navigate("/login")
}
onMount(async () => {
if (!$user) {
return navigate("/login")
}
})
</script>
<div class="flex justify-center py-8 px-4" in:fly={{y: 20}}>
<div class="flex flex-col gap-4 max-w-2xl">
<div class="flex justify-center items-center flex-col mb-4">
<h1 class="staatliches text-6xl">Your Keys</h1>
<p>
Your account is identified across the network using
a public/private <Anchor href={keypairUrl} external>keypair</Anchor>.
This allows you to fully own your account, and move to another app if needed.
</p>
</div>
<div class="flex flex-col gap-8 w-full">
<div class="flex flex-col gap-1">
<strong>Public Key</strong>
<Input disabled value={$user.pubkey}>
<i slot="after" class="fa-solid fa-copy cursor-pointer" on:click={() => copyKey('public')} />
</Input>
<p class="text-sm text-light">
Your public key identifies your account. You can share this with people
trying to find you on nostr.
</p>
</div>
<div class="flex flex-col gap-1">
<strong>Private Key</strong>
<Input disabled type="password" value={$user.privkey}>
<i slot="after" class="fa-solid fa-copy cursor-pointer" on:click={() => copyKey('private')} />
</Input>
<p class="text-sm text-light">
Your private key is used to prove your identity by cryptographically signing
messages. <strong>Do not share this with anyone.</strong> Be careful about
copying this into other apps - instead, consider
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

@ -62,7 +62,7 @@ dispatch.addMethod("room/update", async (topic, {id, ...room}) => {
dispatch.addMethod("message/create", async (topic, roomId, content) => { dispatch.addMethod("message/create", async (topic, roomId, content) => {
const [relay] = get(relays) const [relay] = get(relays)
const event = nostr.event(42, content, [["e", roomId, relay, type]]) const event = nostr.event(42, content, [["e", roomId, relay, "root"]])
await nostr.publish(event) await nostr.publish(event)