From 5621ffd1eba5cc5c8f8fe78d7bfb197638ba418e Mon Sep 17 00:00:00 2001 From: Jon Staab Date: Mon, 14 Oct 2024 12:35:08 -0700 Subject: [PATCH] Improve login screen --- src/app/components/ChatItem.svelte | 2 +- src/app/components/InfoKeys.svelte | 27 +++++ src/app/components/LogIn.svelte | 100 ++++++++++-------- .../components/LogInInfoRemoteSigner.svelte | 10 ++ .../icons/Key Minimalistic Square 3.svg | 5 + src/lib/components/Divider.svelte | 2 +- src/lib/components/Field.svelte | 2 +- src/lib/components/Icon.svelte | 2 + src/lib/components/SearchSelect.svelte | 73 +++++++++++++ src/lib/components/Tippy.svelte | 4 +- src/lib/editor/SuggestionString.svelte | 5 + src/lib/editor/Suggestions.svelte | 4 +- src/lib/editor/util.ts | 14 +-- src/routes/home/[chat]/+page.svelte | 2 +- 14 files changed, 196 insertions(+), 56 deletions(-) create mode 100644 src/app/components/InfoKeys.svelte create mode 100644 src/app/components/LogInInfoRemoteSigner.svelte create mode 100644 src/assets/icons/Key Minimalistic Square 3.svg create mode 100644 src/lib/components/SearchSelect.svelte create mode 100644 src/lib/editor/SuggestionString.svelte diff --git a/src/app/components/ChatItem.svelte b/src/app/components/ChatItem.svelte index 43f0d87f..727a9af5 100644 --- a/src/app/components/ChatItem.svelte +++ b/src/app/components/ChatItem.svelte @@ -16,7 +16,7 @@ export let messages: TrustedEvent[] const message = messages[0] - const others = remove($pubkey, pubkeys) + const others = remove($pubkey!, pubkeys) const active = $page.params.chat === id const missingInbox = derived(inboxRelaySelectionsByPubkey, $m => others.some(pk => !$m.has(pk))) diff --git a/src/app/components/InfoKeys.svelte b/src/app/components/InfoKeys.svelte new file mode 100644 index 00000000..e9803980 --- /dev/null +++ b/src/app/components/InfoKeys.svelte @@ -0,0 +1,27 @@ + + +
+ +
What is a private key?
+
+

+ Most software keeps track of users by giving them a username and password. This gives the service + total control over their users, allowing them to ban them at any time, or sell their activity. +

+

+ On Nostr, you control your own identity and + social data, through the magic of crytography. The basic idea is that you have a public key, + which acts as your user id, and a private key which allows you to authenticate any message + you send. +

+

+ It's very important to keep private keys safe, but this can sometimes be confusing for newcomers. This is why + flotilla supports remote signer login. These services can store your keys securely for you, + giving you access using a username and password. +

+ +
diff --git a/src/app/components/LogIn.svelte b/src/app/components/LogIn.svelte index af400085..5c9cac76 100644 --- a/src/app/components/LogIn.svelte +++ b/src/app/components/LogIn.svelte @@ -3,10 +3,14 @@ import {addSession, loadHandle, nip46Perms, type Session} from "@welshman/app" import Icon from "@lib/components/Icon.svelte" import Field from "@lib/components/Field.svelte" + import Tippy from "@lib/components/Tippy.svelte" import Button from "@lib/components/Button.svelte" + import Divider from "@lib/components/Divider.svelte" import Spinner from "@lib/components/Spinner.svelte" + import SearchSelect from "@lib/components/SearchSelect.svelte" import SignUp from "@app/components/SignUp.svelte" - import InfoNostr from "@app/components/LogIn.svelte" + import InfoNostr from "@app/components/InfoNostr.svelte" + import LogInInfoRemoteSigner from "@app/components/LogInInfoRemoteSigner.svelte" import {pushModal, clearModal} from "@app/modal" import {pushToast} from "@app/toast" import {loadUserData} from "@app/commands" @@ -33,17 +37,31 @@ } const loginWithNip46 = withLoading(async () => { - const secret = makeSecret() - const handle = await loadHandle(`${username}@${handler.domain}`) + const rootHandle = await loadHandle(`_@${domain}`) - if (!handle?.pubkey) { + if (!rootHandle?.pubkey) { + return pushToast({ + theme: "error", + message: "Sorry, we couldn't find that remote signer.", + }) + } + + const secret = makeSecret() + const {pubkey, nip46, relays = []} = await loadHandle(`${username}@${domain}`) || {} + + if (!pubkey) { return pushToast({ theme: "error", message: "Sorry, it looks like you don't have an account yet. Try signing up instead.", }) } - const {pubkey, relays = []} = handle + const handler = { + domain, + pubkey: rootHandle.pubkey, + relays: rootHandle.nip46 || rootHandle.relays || nip46 || relays, + } + const broker = Nip46Broker.get(pubkey, secret, handler) if (await broker.connect("", nip46Perms)) { @@ -69,13 +87,8 @@ } }) - const handler = { - domain: "nsec.app", - relays: ["wss://relay.nsec.app"], - pubkey: "e24a86943d37a91ab485d6f9a7c66097c25ddd67e8bd1b75ed252a3c266cf9bb", - } - let username = "" + let domain = 'nsec.app' let loading = false @@ -86,37 +99,40 @@ , which allows you to own your social identity.

- -
- - {#if getNip07()} - - {/if} -
-
-
- + Or + {#if getNip07()} + -
- Need an account? - -
+ {/if} + +
+ Need an account? +
diff --git a/src/app/components/LogInInfoRemoteSigner.svelte b/src/app/components/LogInInfoRemoteSigner.svelte new file mode 100644 index 00000000..cc4c5106 --- /dev/null +++ b/src/app/components/LogInInfoRemoteSigner.svelte @@ -0,0 +1,10 @@ + + +

+ A remote signer is a simple way to protect your private key. + +

diff --git a/src/assets/icons/Key Minimalistic Square 3.svg b/src/assets/icons/Key Minimalistic Square 3.svg new file mode 100644 index 00000000..19e16697 --- /dev/null +++ b/src/assets/icons/Key Minimalistic Square 3.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/lib/components/Divider.svelte b/src/lib/components/Divider.svelte index f6a5a63d..ac959b5f 100644 --- a/src/lib/components/Divider.svelte +++ b/src/lib/components/Divider.svelte @@ -1,4 +1,4 @@ -
+

diff --git a/src/lib/components/Field.svelte b/src/lib/components/Field.svelte index 0359efb1..b60cddba 100644 --- a/src/lib/components/Field.svelte +++ b/src/lib/components/Field.svelte @@ -1,4 +1,4 @@ -
+
diff --git a/src/lib/components/Icon.svelte b/src/lib/components/Icon.svelte index 713bd6f3..738db57d 100644 --- a/src/lib/components/Icon.svelte +++ b/src/lib/components/Icon.svelte @@ -46,6 +46,7 @@ import InfoCircle from "@assets/icons/Info Circle.svg?dataurl" import InfoSquare from "@assets/icons/Info Square.svg?dataurl" import Key from "@assets/icons/Key.svg?dataurl" + import KeyMinimalisticSquare3 from "@assets/icons/Key Minimalistic Square 3.svg?dataurl" import LinkRound from "@assets/icons/Link Round.svg?dataurl" import Login from "@assets/icons/Login.svg?dataurl" import Login2 from "@assets/icons/Login 2.svg?dataurl" @@ -117,6 +118,7 @@ "info-circle": InfoCircle, "info-square": InfoSquare, key: Key, + 'key-minimalistic-square-3': KeyMinimalisticSquare3, "link-round": LinkRound, login: Login, "login-2": Login2, diff --git a/src/lib/components/SearchSelect.svelte b/src/lib/components/SearchSelect.svelte new file mode 100644 index 00000000..4304ff86 --- /dev/null +++ b/src/lib/components/SearchSelect.svelte @@ -0,0 +1,73 @@ + + +
+ + input.getBoundingClientRect(), + }} /> +
diff --git a/src/lib/components/Tippy.svelte b/src/lib/components/Tippy.svelte index 4066ac74..046cb405 100644 --- a/src/lib/components/Tippy.svelte +++ b/src/lib/components/Tippy.svelte @@ -1,4 +1,6 @@ + +{value} diff --git a/src/lib/editor/Suggestions.svelte b/src/lib/editor/Suggestions.svelte index ac034532..c51ce763 100644 --- a/src/lib/editor/Suggestions.svelte +++ b/src/lib/editor/Suggestions.svelte @@ -67,7 +67,7 @@ transition:fly|local={{duration: 200}} class="mt-2 max-h-[350px] overflow-y-auto overflow-x-hidden shadow-xl {$$props.class} bg-alt" style={$$props.style}> - {#if term && allowCreate} + {#if term && allowCreate && !items.includes(term)}