Add KeygenStep, only show ExtensionStep when window.nostr is present
This commit is contained in:
parent
f2bfa6e2f6
commit
49bde675c3
|
@ -77,10 +77,11 @@ export class NKeyStorage implements ReadonlyMap<string, NostrSigner> {
|
|||
return this.#keypairs.has(pubkey);
|
||||
}
|
||||
|
||||
add(secretKey: Uint8Array): void {
|
||||
add(secretKey: Uint8Array): NostrSigner {
|
||||
const pubkey = getPublicKey(secretKey);
|
||||
this.#keypairs.set(pubkey, secretKey);
|
||||
this.#syncStorage();
|
||||
return this.get(pubkey)!;
|
||||
}
|
||||
|
||||
*entries(): IterableIterator<[string, NostrSigner]> {
|
||||
|
|
|
@ -10,7 +10,7 @@ interface IEmojiGraphic {
|
|||
const EmojiGraphic: React.FC<IEmojiGraphic> = ({ emoji }) => {
|
||||
return (
|
||||
<div className='flex items-center justify-center'>
|
||||
<div className='my-6 rounded-full bg-gray-100 p-8 dark:bg-gray-800'>
|
||||
<div className='rounded-full bg-gray-100 p-8 dark:bg-gray-800'>
|
||||
<Emoji className='h-24 w-24' emoji={emoji} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import { NostrSigner } from 'nspec';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import AccountStep from './steps/account-step';
|
||||
import ExtensionStep from './steps/extension-step';
|
||||
import IdentityStep from './steps/identity-step';
|
||||
import KeyStep from './steps/key-step';
|
||||
import KeygenStep from './steps/keygen-step';
|
||||
import RegisterStep from './steps/register-step';
|
||||
|
||||
interface INostrSigninModal {
|
||||
|
@ -11,8 +13,9 @@ interface INostrSigninModal {
|
|||
}
|
||||
|
||||
const NostrSigninModal: React.FC<INostrSigninModal> = ({ onClose }) => {
|
||||
const [step, setStep] = useState(0);
|
||||
const [step, setStep] = useState(window.nostr ? 0 : 1);
|
||||
|
||||
const [, setSigner] = useState<NostrSigner | undefined>();
|
||||
const [accountId, setAccountId] = useState<string | undefined>();
|
||||
|
||||
const handleClose = () => onClose('NOSTR_SIGNIN');
|
||||
|
@ -28,6 +31,8 @@ const NostrSigninModal: React.FC<INostrSigninModal> = ({ onClose }) => {
|
|||
return <AccountStep accountId={accountId!} setStep={setStep} onClose={handleClose} />;
|
||||
case 4:
|
||||
return <RegisterStep onClose={handleClose} />;
|
||||
case 5:
|
||||
return <KeygenStep setSigner={setSigner} setStep={setStep} onClose={handleClose} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -53,7 +53,9 @@ const IdentityStep: React.FC<IIdentityStep> = ({ setAccountId, setStep, onClose
|
|||
<Modal title={<FormattedMessage id='nostr_signin.identity.title' defaultMessage='Who are you?' />} onClose={onClose}>
|
||||
<Form>
|
||||
<Stack className='mt-3' space={3}>
|
||||
<div className='my-3'>
|
||||
<NostrExtensionIndicator />
|
||||
</div>
|
||||
|
||||
<EmojiGraphic emoji='🕵️' />
|
||||
|
||||
|
|
|
@ -14,13 +14,13 @@ interface IKeyStep {
|
|||
const KeyStep: React.FC<IKeyStep> = ({ setStep, onClose }) => {
|
||||
return (
|
||||
<Modal title={<FormattedMessage id='nostr_signin.key.title' defaultMessage='You need a key to continue' />} onClose={onClose}>
|
||||
<Stack className='my-3' space={6} justifyContent='center'>
|
||||
<Stack className='my-3' space={6}>
|
||||
<NostrExtensionIndicator />
|
||||
|
||||
<EmojiGraphic emoji='🔑' />
|
||||
|
||||
<Stack space={3} alignItems='center'>
|
||||
<Button theme='accent' size='lg'>
|
||||
<Button theme='accent' size='lg' onClick={() => setStep(5)}>
|
||||
Generate key
|
||||
</Button>
|
||||
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
import { generateSecretKey, getPublicKey, nip19 } from 'nostr-tools';
|
||||
import { NostrSigner } from 'nspec';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { Button, Stack, Modal } from 'soapbox/components/ui';
|
||||
import { NKeys } from 'soapbox/features/nostr/keys';
|
||||
import { useInstance } from 'soapbox/hooks';
|
||||
import { download } from 'soapbox/utils/download';
|
||||
import { slugify } from 'soapbox/utils/input';
|
||||
|
||||
import EmojiGraphic from '../components/emoji-graphic';
|
||||
|
||||
interface IKeygenStep {
|
||||
setSigner(signer: NostrSigner): void;
|
||||
setStep(step: number): void;
|
||||
onClose(): void;
|
||||
}
|
||||
|
||||
const KeygenStep: React.FC<IKeygenStep> = ({ setSigner, setStep, onClose }) => {
|
||||
const instance = useInstance();
|
||||
|
||||
const secretKey = useMemo(() => generateSecretKey(), []);
|
||||
const pubkey = useMemo(() => getPublicKey(secretKey), [secretKey]);
|
||||
|
||||
const nsec = useMemo(() => nip19.nsecEncode(secretKey), [secretKey]);
|
||||
const npub = useMemo(() => nip19.npubEncode(pubkey), [pubkey]);
|
||||
|
||||
const [downloaded, setDownloaded] = useState(false);
|
||||
|
||||
const handleDownload = () => {
|
||||
download(nsec, `${slugify(instance.title)}-${npub.slice(5, 9)}.nsec`);
|
||||
setDownloaded(true);
|
||||
};
|
||||
|
||||
const handleNext = () => {
|
||||
const signer = NKeys.add(secretKey);
|
||||
setSigner(signer);
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal title={<FormattedMessage id='nostr_signin.keygen.title' defaultMessage='Your new key' />} onClose={onClose}>
|
||||
<Stack className='my-3' space={6}>
|
||||
<EmojiGraphic emoji='🔑' />
|
||||
|
||||
<Stack alignItems='center'>
|
||||
<Button theme='primary' size='lg' icon={require('@tabler/icons/download.svg')} onClick={handleDownload}>
|
||||
Download key
|
||||
</Button>
|
||||
</Stack>
|
||||
|
||||
<Stack space={3} alignItems='end'>
|
||||
<Button theme='accent' disabled={!downloaded} size='lg' onClick={handleNext}>
|
||||
Next
|
||||
</Button>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default KeygenStep;
|
|
@ -8,6 +8,15 @@ const normalizeUsername = (username: string): string => {
|
|||
}
|
||||
};
|
||||
|
||||
function slugify(text: string): string {
|
||||
return text
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace(/[^\w]/g, '-') // replace non-word characters with a hyphen
|
||||
.replace(/-+/g, '-'); // replace multiple hyphens with a single hyphen
|
||||
}
|
||||
|
||||
export {
|
||||
normalizeUsername,
|
||||
slugify,
|
||||
};
|
Loading…
Reference in New Issue