From ec2b11bd750d7f574334ba7b745c0ccc1ce7375a Mon Sep 17 00:00:00 2001 From: Kieran Date: Tue, 29 Aug 2023 14:55:30 +0100 Subject: [PATCH] Nip7os interface Light theme tweaks --- packages/app/custom.d.ts | 2 +- packages/app/src/Element/ProxyImg.tsx | 1 + packages/app/src/Hooks/useLoginHandler.tsx | 16 +++++--- packages/app/src/Login/LoginSession.ts | 1 + packages/app/src/Login/MultiAccountStore.ts | 10 +++++ packages/app/src/Login/Nip7OsSigner.ts | 44 +++++++++++++++++++++ packages/app/src/Login/index.ts | 14 +++++++ packages/app/src/Pages/new/NewUserFlow.tsx | 10 ++++- packages/app/src/index.css | 19 ++++----- 9 files changed, 99 insertions(+), 18 deletions(-) create mode 100644 packages/app/src/Login/Nip7OsSigner.ts diff --git a/packages/app/custom.d.ts b/packages/app/custom.d.ts index 8e871bb8..67cd96ee 100644 --- a/packages/app/custom.d.ts +++ b/packages/app/custom.d.ts @@ -33,4 +33,4 @@ declare module "translations/*.json" { declare module "emojilib" { const value: Record; export default value; -} +} \ No newline at end of file diff --git a/packages/app/src/Element/ProxyImg.tsx b/packages/app/src/Element/ProxyImg.tsx index 25f6dd04..196dd4ba 100644 --- a/packages/app/src/Element/ProxyImg.tsx +++ b/packages/app/src/Element/ProxyImg.tsx @@ -36,6 +36,7 @@ export const ProxyImg = (props: ProxyImgProps) => { { if (props.onError) { props.onError(e); diff --git a/packages/app/src/Hooks/useLoginHandler.tsx b/packages/app/src/Hooks/useLoginHandler.tsx index 071f4de4..a1036082 100644 --- a/packages/app/src/Hooks/useLoginHandler.tsx +++ b/packages/app/src/Hooks/useLoginHandler.tsx @@ -16,6 +16,7 @@ export default function useLoginHandler() { defaultMessage: "Can't login with private key on an insecure connection, please use a Nostr key manager extension instead", }); + // private key logins if (key.startsWith("nsec")) { if (!hasSubtleCrypto) { throw new Error(insecureMsg); @@ -26,12 +27,6 @@ export default function useLoginHandler() { } else { throw new Error("INVALID PRIVATE KEY"); } - } else if (key.startsWith("npub")) { - const hexKey = bech32ToHex(key); - LoginStore.loginWithPubkey(hexKey, LoginSessionType.PublicKey); - } else if (key.match(EmailRegex)) { - const hexKey = await getNip05PubKey(key); - LoginStore.loginWithPubkey(hexKey, LoginSessionType.PublicKey); } else if (key.match(MnemonicRegex)?.length === 24) { if (!hasSubtleCrypto) { throw new Error(insecureMsg); @@ -44,6 +39,15 @@ export default function useLoginHandler() { throw new Error(insecureMsg); } LoginStore.loginWithPrivateKey(key); + } + + // public key logins + if (key.startsWith("npub")) { + const hexKey = bech32ToHex(key); + LoginStore.loginWithPubkey(hexKey, LoginSessionType.PublicKey); + } else if (key.match(EmailRegex)) { + const hexKey = await getNip05PubKey(key); + LoginStore.loginWithPubkey(hexKey, LoginSessionType.PublicKey); } else if (key.startsWith("bunker://")) { const nip46 = new Nip46Signer(key); await nip46.init(); diff --git a/packages/app/src/Login/LoginSession.ts b/packages/app/src/Login/LoginSession.ts index a626de72..263b0179 100644 --- a/packages/app/src/Login/LoginSession.ts +++ b/packages/app/src/Login/LoginSession.ts @@ -15,6 +15,7 @@ export enum LoginSessionType { PublicKey = "public_key", Nip7 = "nip7", Nip46 = "nip46", + Nip7os = "nip7_os" } export interface LoginSession { diff --git a/packages/app/src/Login/MultiAccountStore.ts b/packages/app/src/Login/MultiAccountStore.ts index 6f5a6248..6d205731 100644 --- a/packages/app/src/Login/MultiAccountStore.ts +++ b/packages/app/src/Login/MultiAccountStore.ts @@ -7,6 +7,7 @@ import { deepClone, sanitizeRelayUrl, unwrap, ExternalStore } from "@snort/share import { DefaultRelays } from "Const"; import { LoginSession, LoginSessionType } from "Login"; import { DefaultPreferences, UserPreferences } from "./Preferences"; +import { Nip7OsSigner } from "./Nip7OsSigner"; const AccountStoreKey = "sessions"; const LoggedOut = { @@ -146,6 +147,12 @@ export class MultiAccountStore extends ExternalStore { }, preferences: deepClone(DefaultPreferences), } as LoginSession; + + if("nostr_os" in window && window.nostr_os) { + window.nostr_os.saveKey(key); + newSession.type = LoginSessionType.Nip7os; + newSession.privateKey = undefined; + } newSession.publisher = this.#createPublisher(newSession); this.#accounts.set(pubKey, newSession); @@ -190,6 +197,9 @@ export class MultiAccountStore extends ExternalStore { const nip46 = new Nip46Signer(`bunker://${unwrap(l.publicKey)}?${[...relayArgs].join("&")}`, inner); return new EventPublisher(nip46, unwrap(l.publicKey)); } + case LoginSessionType.Nip7os: { + return new EventPublisher(new Nip7OsSigner(), unwrap(l.publicKey)); + } default: { if (l.publicKey) { return new EventPublisher(new Nip7Signer(), l.publicKey); diff --git a/packages/app/src/Login/Nip7OsSigner.ts b/packages/app/src/Login/Nip7OsSigner.ts new file mode 100644 index 00000000..ce6fe176 --- /dev/null +++ b/packages/app/src/Login/Nip7OsSigner.ts @@ -0,0 +1,44 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { EventSigner, NostrEvent } from "@snort/system"; +import { Nip7os } from "Login"; + +export class Nip7OsSigner implements EventSigner { + #interface: Nip7os; + + constructor() { + if("nostr_os" in window && window.nostr_os) { + this.#interface = window.nostr_os; + } else { + throw new Error("Nost OS extension not available") + } + } + + init(): Promise { + return Promise.resolve(); + } + + getPubKey(): string | Promise { + return this.#interface.getPublicKey(); + } + + nip4Encrypt(content: string, key: string): Promise { + return Promise.resolve(this.#interface.nip04_encrypt(content, key)); + } + + nip4Decrypt(content: string, otherKey: string): Promise { + return Promise.resolve(this.#interface.nip04_decrypt(content, otherKey)); + } + + nip44Encrypt(content: string, key: string): Promise { + throw new Error("Method not implemented."); + } + + nip44Decrypt(content: string, otherKey: string): Promise { + throw new Error("Method not implemented."); + } + + sign(ev: NostrEvent): Promise { + const ret = this.#interface.signEvent(JSON.stringify(ev)); + return Promise.resolve(JSON.parse(ret) as NostrEvent); + } +} \ No newline at end of file diff --git a/packages/app/src/Login/index.ts b/packages/app/src/Login/index.ts index d1ca2401..4a83578b 100644 --- a/packages/app/src/Login/index.ts +++ b/packages/app/src/Login/index.ts @@ -1,6 +1,20 @@ import { MultiAccountStore } from "./MultiAccountStore"; export const LoginStore = new MultiAccountStore(); +export interface Nip7os { + getPublicKey: () => string + signEvent: (ev: string) => string + saveKey: (key: string) => void + nip04_encrypt: (content:string, to: string) => string + nip04_decrypt: (content:string, from: string) => string +} + +declare global { + interface Window { + nostr_os?: Nip7os; + } +} + export * from "./Preferences"; export * from "./LoginSession"; export * from "./Functions"; diff --git a/packages/app/src/Pages/new/NewUserFlow.tsx b/packages/app/src/Pages/new/NewUserFlow.tsx index 45e70ac1..9a18409b 100644 --- a/packages/app/src/Pages/new/NewUserFlow.tsx +++ b/packages/app/src/Pages/new/NewUserFlow.tsx @@ -8,7 +8,7 @@ import { hexToBech32 } from "SnortUtils"; import { hexToMnemonic } from "nip6"; import useLogin from "Hooks/useLogin"; import { PROFILE } from "."; -import { DefaultPreferences, updatePreferences } from "Login"; +import { DefaultPreferences, LoginStore, updatePreferences } from "Login"; import { AllLanguageCodes } from "Pages/settings/Preferences"; import messages from "./messages"; @@ -136,7 +136,13 @@ export default function NewUserFlow() {
-
diff --git a/packages/app/src/index.css b/packages/app/src/index.css index 2e49d86d..bb7815e6 100644 --- a/packages/app/src/index.css +++ b/packages/app/src/index.css @@ -3,7 +3,7 @@ --font-color: #fff; --font-secondary-color: #a7a7a7; --font-tertiary-color: #a3a3a3; - --border-color: rgba(163, 163, 163, 0.3); + --border-color: var(--gray-superdark); --font-size: 15px; --font-size-small: 13px; --font-size-tiny: 11px; @@ -71,21 +71,22 @@ html { html.light { --bg-color: #f8f8f8; - --font-color: #27272a; + --font-color: #2F3F64; --font-secondary-color: #71717a; --font-tertiary-color: #52525b; - --border-color: rgba(167, 167, 167, 0.3); + --border-color: #DEE1E8; --highlight: #7139f1; --modal-bg-color: rgba(240, 240, 240, 0.8); - --gray: #aaa; - --gray-secondary: #bbb; - --gray-tertiary: #ccc; + --gray: #999; + --gray-secondary: #aaa; + --gray-tertiary: #bbb; --gray-superlight: #333; --gray-light: #555; - --gray-dark: #2b2b2b; - --gray-superdark: #eee; + --gray-dark: #ccc; + --gray-superdark: #ddd; + --gray-ultradark: #eee; --dm-gradient: var(--gray); --invoice-gradient: linear-gradient(45deg, var(--gray-superdark) 50%, #f7b73333, #fc4a1a33); @@ -125,7 +126,7 @@ code { } .main-content { - border: 1px solid var(--gray-superdark); + border: 1px solid var(--border-color); } }