mirror of
https://github.com/coracle-social/coracle.git
synced 2024-10-06 11:43:30 +00:00
Add keys page
This commit is contained in:
parent
20f8d52c78
commit
b40515b133
@ -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">
|
||||||
|
@ -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>
|
||||||
|
@ -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(() => {
|
||||||
|
@ -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>
|
||||||
|
@ -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
71
src/routes/Keys.svelte
Normal 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>
|
@ -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)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user