forked from Kieran/snort
Nip7os interface
Light theme tweaks
This commit is contained in:
parent
8a3133af70
commit
ec2b11bd75
2
packages/app/custom.d.ts
vendored
2
packages/app/custom.d.ts
vendored
@ -33,4 +33,4 @@ declare module "translations/*.json" {
|
|||||||
declare module "emojilib" {
|
declare module "emojilib" {
|
||||||
const value: Record<string, string>;
|
const value: Record<string, string>;
|
||||||
export default value;
|
export default value;
|
||||||
}
|
}
|
@ -36,6 +36,7 @@ export const ProxyImg = (props: ProxyImgProps) => {
|
|||||||
<img
|
<img
|
||||||
{...props}
|
{...props}
|
||||||
src={props.src ? proxy(props.src, props.size) : ""}
|
src={props.src ? proxy(props.src, props.size) : ""}
|
||||||
|
width={props.size} height={props.size}
|
||||||
onError={e => {
|
onError={e => {
|
||||||
if (props.onError) {
|
if (props.onError) {
|
||||||
props.onError(e);
|
props.onError(e);
|
||||||
|
@ -16,6 +16,7 @@ export default function useLoginHandler() {
|
|||||||
defaultMessage:
|
defaultMessage:
|
||||||
"Can't login with private key on an insecure connection, please use a Nostr key manager extension instead",
|
"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 (key.startsWith("nsec")) {
|
||||||
if (!hasSubtleCrypto) {
|
if (!hasSubtleCrypto) {
|
||||||
throw new Error(insecureMsg);
|
throw new Error(insecureMsg);
|
||||||
@ -26,12 +27,6 @@ export default function useLoginHandler() {
|
|||||||
} else {
|
} else {
|
||||||
throw new Error("INVALID PRIVATE KEY");
|
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) {
|
} else if (key.match(MnemonicRegex)?.length === 24) {
|
||||||
if (!hasSubtleCrypto) {
|
if (!hasSubtleCrypto) {
|
||||||
throw new Error(insecureMsg);
|
throw new Error(insecureMsg);
|
||||||
@ -44,6 +39,15 @@ export default function useLoginHandler() {
|
|||||||
throw new Error(insecureMsg);
|
throw new Error(insecureMsg);
|
||||||
}
|
}
|
||||||
LoginStore.loginWithPrivateKey(key);
|
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://")) {
|
} else if (key.startsWith("bunker://")) {
|
||||||
const nip46 = new Nip46Signer(key);
|
const nip46 = new Nip46Signer(key);
|
||||||
await nip46.init();
|
await nip46.init();
|
||||||
|
@ -15,6 +15,7 @@ export enum LoginSessionType {
|
|||||||
PublicKey = "public_key",
|
PublicKey = "public_key",
|
||||||
Nip7 = "nip7",
|
Nip7 = "nip7",
|
||||||
Nip46 = "nip46",
|
Nip46 = "nip46",
|
||||||
|
Nip7os = "nip7_os"
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LoginSession {
|
export interface LoginSession {
|
||||||
|
@ -7,6 +7,7 @@ import { deepClone, sanitizeRelayUrl, unwrap, ExternalStore } from "@snort/share
|
|||||||
import { DefaultRelays } from "Const";
|
import { DefaultRelays } from "Const";
|
||||||
import { LoginSession, LoginSessionType } from "Login";
|
import { LoginSession, LoginSessionType } from "Login";
|
||||||
import { DefaultPreferences, UserPreferences } from "./Preferences";
|
import { DefaultPreferences, UserPreferences } from "./Preferences";
|
||||||
|
import { Nip7OsSigner } from "./Nip7OsSigner";
|
||||||
|
|
||||||
const AccountStoreKey = "sessions";
|
const AccountStoreKey = "sessions";
|
||||||
const LoggedOut = {
|
const LoggedOut = {
|
||||||
@ -146,6 +147,12 @@ export class MultiAccountStore extends ExternalStore<LoginSession> {
|
|||||||
},
|
},
|
||||||
preferences: deepClone(DefaultPreferences),
|
preferences: deepClone(DefaultPreferences),
|
||||||
} as LoginSession;
|
} 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);
|
newSession.publisher = this.#createPublisher(newSession);
|
||||||
|
|
||||||
this.#accounts.set(pubKey, newSession);
|
this.#accounts.set(pubKey, newSession);
|
||||||
@ -190,6 +197,9 @@ export class MultiAccountStore extends ExternalStore<LoginSession> {
|
|||||||
const nip46 = new Nip46Signer(`bunker://${unwrap(l.publicKey)}?${[...relayArgs].join("&")}`, inner);
|
const nip46 = new Nip46Signer(`bunker://${unwrap(l.publicKey)}?${[...relayArgs].join("&")}`, inner);
|
||||||
return new EventPublisher(nip46, unwrap(l.publicKey));
|
return new EventPublisher(nip46, unwrap(l.publicKey));
|
||||||
}
|
}
|
||||||
|
case LoginSessionType.Nip7os: {
|
||||||
|
return new EventPublisher(new Nip7OsSigner(), unwrap(l.publicKey));
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
if (l.publicKey) {
|
if (l.publicKey) {
|
||||||
return new EventPublisher(new Nip7Signer(), l.publicKey);
|
return new EventPublisher(new Nip7Signer(), l.publicKey);
|
||||||
|
44
packages/app/src/Login/Nip7OsSigner.ts
Normal file
44
packages/app/src/Login/Nip7OsSigner.ts
Normal file
@ -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<void> {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
getPubKey(): string | Promise<string> {
|
||||||
|
return this.#interface.getPublicKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
nip4Encrypt(content: string, key: string): Promise<string> {
|
||||||
|
return Promise.resolve(this.#interface.nip04_encrypt(content, key));
|
||||||
|
}
|
||||||
|
|
||||||
|
nip4Decrypt(content: string, otherKey: string): Promise<string> {
|
||||||
|
return Promise.resolve(this.#interface.nip04_decrypt(content, otherKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
nip44Encrypt(content: string, key: string): Promise<string> {
|
||||||
|
throw new Error("Method not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
nip44Decrypt(content: string, otherKey: string): Promise<string> {
|
||||||
|
throw new Error("Method not implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
sign(ev: NostrEvent): Promise<NostrEvent> {
|
||||||
|
const ret = this.#interface.signEvent(JSON.stringify(ev));
|
||||||
|
return Promise.resolve(JSON.parse(ret) as NostrEvent);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,20 @@
|
|||||||
import { MultiAccountStore } from "./MultiAccountStore";
|
import { MultiAccountStore } from "./MultiAccountStore";
|
||||||
export const LoginStore = new 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 "./Preferences";
|
||||||
export * from "./LoginSession";
|
export * from "./LoginSession";
|
||||||
export * from "./Functions";
|
export * from "./Functions";
|
||||||
|
@ -8,7 +8,7 @@ import { hexToBech32 } from "SnortUtils";
|
|||||||
import { hexToMnemonic } from "nip6";
|
import { hexToMnemonic } from "nip6";
|
||||||
import useLogin from "Hooks/useLogin";
|
import useLogin from "Hooks/useLogin";
|
||||||
import { PROFILE } from ".";
|
import { PROFILE } from ".";
|
||||||
import { DefaultPreferences, updatePreferences } from "Login";
|
import { DefaultPreferences, LoginStore, updatePreferences } from "Login";
|
||||||
import { AllLanguageCodes } from "Pages/settings/Preferences";
|
import { AllLanguageCodes } from "Pages/settings/Preferences";
|
||||||
|
|
||||||
import messages from "./messages";
|
import messages from "./messages";
|
||||||
@ -136,7 +136,13 @@ export default function NewUserFlow() {
|
|||||||
</h2>
|
</h2>
|
||||||
<Copy text={hexToMnemonic(login.generatedEntropy ?? "")} />
|
<Copy text={hexToMnemonic(login.generatedEntropy ?? "")} />
|
||||||
<div className="next-actions">
|
<div className="next-actions">
|
||||||
<button type="button" onClick={() => navigate(PROFILE)}>
|
<button type="button" onClick={() => {
|
||||||
|
LoginStore.updateSession({
|
||||||
|
...login,
|
||||||
|
generatedEntropy: undefined
|
||||||
|
})
|
||||||
|
navigate(PROFILE)
|
||||||
|
}}>
|
||||||
<FormattedMessage {...messages.KeysSaved} />{" "}
|
<FormattedMessage {...messages.KeysSaved} />{" "}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
--font-color: #fff;
|
--font-color: #fff;
|
||||||
--font-secondary-color: #a7a7a7;
|
--font-secondary-color: #a7a7a7;
|
||||||
--font-tertiary-color: #a3a3a3;
|
--font-tertiary-color: #a3a3a3;
|
||||||
--border-color: rgba(163, 163, 163, 0.3);
|
--border-color: var(--gray-superdark);
|
||||||
--font-size: 15px;
|
--font-size: 15px;
|
||||||
--font-size-small: 13px;
|
--font-size-small: 13px;
|
||||||
--font-size-tiny: 11px;
|
--font-size-tiny: 11px;
|
||||||
@ -71,21 +71,22 @@ html {
|
|||||||
|
|
||||||
html.light {
|
html.light {
|
||||||
--bg-color: #f8f8f8;
|
--bg-color: #f8f8f8;
|
||||||
--font-color: #27272a;
|
--font-color: #2F3F64;
|
||||||
--font-secondary-color: #71717a;
|
--font-secondary-color: #71717a;
|
||||||
--font-tertiary-color: #52525b;
|
--font-tertiary-color: #52525b;
|
||||||
--border-color: rgba(167, 167, 167, 0.3);
|
--border-color: #DEE1E8;
|
||||||
|
|
||||||
--highlight: #7139f1;
|
--highlight: #7139f1;
|
||||||
--modal-bg-color: rgba(240, 240, 240, 0.8);
|
--modal-bg-color: rgba(240, 240, 240, 0.8);
|
||||||
|
|
||||||
--gray: #aaa;
|
--gray: #999;
|
||||||
--gray-secondary: #bbb;
|
--gray-secondary: #aaa;
|
||||||
--gray-tertiary: #ccc;
|
--gray-tertiary: #bbb;
|
||||||
--gray-superlight: #333;
|
--gray-superlight: #333;
|
||||||
--gray-light: #555;
|
--gray-light: #555;
|
||||||
--gray-dark: #2b2b2b;
|
--gray-dark: #ccc;
|
||||||
--gray-superdark: #eee;
|
--gray-superdark: #ddd;
|
||||||
|
--gray-ultradark: #eee;
|
||||||
|
|
||||||
--dm-gradient: var(--gray);
|
--dm-gradient: var(--gray);
|
||||||
--invoice-gradient: linear-gradient(45deg, var(--gray-superdark) 50%, #f7b73333, #fc4a1a33);
|
--invoice-gradient: linear-gradient(45deg, var(--gray-superdark) 50%, #f7b73333, #fc4a1a33);
|
||||||
@ -125,7 +126,7 @@ code {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.main-content {
|
.main-content {
|
||||||
border: 1px solid var(--gray-superdark);
|
border: 1px solid var(--border-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user