NostrSignin: remove IdentityStep, AccountStep, other useless code
This commit is contained in:
parent
b8b22fc637
commit
5b23166fb7
|
@ -1,37 +1,30 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
import AccountStep from './steps/account-step';
|
|
||||||
import ExtensionStep from './steps/extension-step';
|
import ExtensionStep from './steps/extension-step';
|
||||||
import IdentityStep from './steps/identity-step';
|
|
||||||
import KeyAddStep from './steps/key-add-step';
|
import KeyAddStep from './steps/key-add-step';
|
||||||
import KeyStep from './steps/key-step';
|
import KeyStep from './steps/key-step';
|
||||||
import KeygenStep from './steps/keygen-step';
|
import KeygenStep from './steps/keygen-step';
|
||||||
|
|
||||||
type Step = 'extension' | 'identity' | 'key' | 'keygen' | 'key-add' | 'account';
|
type Step = 'extension' | 'key' | 'keygen' | 'key-add';
|
||||||
|
|
||||||
interface INostrSigninModal {
|
interface INostrSigninModal {
|
||||||
onClose: (type?: string) => void;
|
onClose: (type?: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NostrSigninModal: React.FC<INostrSigninModal> = ({ onClose }) => {
|
const NostrSigninModal: React.FC<INostrSigninModal> = ({ onClose }) => {
|
||||||
const [step, setStep] = useState<Step>(window.nostr ? 'extension' : 'identity');
|
const [step, setStep] = useState<Step>(window.nostr ? 'extension' : 'key-add');
|
||||||
const [accountId, setAccountId] = useState<string | undefined>();
|
|
||||||
|
|
||||||
const handleClose = () => onClose('NOSTR_SIGNIN');
|
const handleClose = () => onClose('NOSTR_SIGNIN');
|
||||||
|
|
||||||
switch (step) {
|
switch (step) {
|
||||||
case 'extension':
|
case 'extension':
|
||||||
return <ExtensionStep setStep={setStep} onClose={handleClose} />;
|
return <ExtensionStep setStep={setStep} onClose={handleClose} />;
|
||||||
case 'identity':
|
|
||||||
return <IdentityStep setAccountId={setAccountId} setStep={setStep} onClose={handleClose} />;
|
|
||||||
case 'key':
|
case 'key':
|
||||||
return <KeyStep setStep={setStep} onClose={handleClose} />;
|
return <KeyStep setStep={setStep} onClose={handleClose} />;
|
||||||
case 'key-add':
|
case 'key-add':
|
||||||
return <KeyAddStep setAccountId={setAccountId} setStep={setStep} onClose={handleClose} />;
|
return <KeyAddStep onClose={handleClose} />;
|
||||||
case 'keygen':
|
case 'keygen':
|
||||||
return <KeygenStep setAccountId={setAccountId} setStep={setStep} onClose={handleClose} />;
|
return <KeygenStep onClose={handleClose} />;
|
||||||
case 'account':
|
|
||||||
return <AccountStep accountId={accountId!} setStep={setStep} onClose={handleClose} />;
|
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,127 +0,0 @@
|
||||||
import { NSchema as n } from '@soapbox/nspec';
|
|
||||||
import { nip19 } from 'nostr-tools';
|
|
||||||
import React, { useMemo, useState } from 'react';
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
|
||||||
|
|
||||||
import { useAccount } from 'soapbox/api/hooks';
|
|
||||||
import { Avatar, Text, Stack, Emoji, Button, Tooltip, Modal } from 'soapbox/components/ui';
|
|
||||||
import { useNostr } from 'soapbox/contexts/nostr-context';
|
|
||||||
import { useNostrReq } from 'soapbox/features/nostr/hooks/useNostrReq';
|
|
||||||
import ModalLoading from 'soapbox/features/ui/components/modal-loading';
|
|
||||||
import { useInstance } from 'soapbox/hooks';
|
|
||||||
|
|
||||||
import { Step } from '../nostr-signin-modal';
|
|
||||||
|
|
||||||
interface IAccountStep {
|
|
||||||
accountId: string;
|
|
||||||
setStep(step: Step): void;
|
|
||||||
onClose(): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const AccountStep: React.FC<IAccountStep> = ({ accountId, setStep, onClose }) => {
|
|
||||||
const { relay, signer } = useNostr();
|
|
||||||
const { account } = useAccount(accountId);
|
|
||||||
const [submitting, setSubmitting] = useState(false);
|
|
||||||
const [submitted, setSubmitted] = useState(false);
|
|
||||||
const instance = useInstance();
|
|
||||||
|
|
||||||
const { events } = useNostrReq((instance.nostr && account?.nostr) ? [{
|
|
||||||
kinds: [7000, 6951],
|
|
||||||
authors: [instance.nostr.pubkey],
|
|
||||||
'#p': [account.nostr.pubkey],
|
|
||||||
}] : []);
|
|
||||||
|
|
||||||
const success = events.find((event) => event.kind === 6951);
|
|
||||||
const feedback = events.find((event) => event.kind === 7000);
|
|
||||||
|
|
||||||
const handleJoin = async () => {
|
|
||||||
if (!relay || !signer || !instance.nostr) return;
|
|
||||||
setSubmitting(true);
|
|
||||||
|
|
||||||
const event = await signer.signEvent({
|
|
||||||
kind: 5951,
|
|
||||||
content: '',
|
|
||||||
tags: [
|
|
||||||
['i', instance.nostr.relay, 'text'],
|
|
||||||
['p', instance.nostr.pubkey, 'text'],
|
|
||||||
],
|
|
||||||
created_at: Math.floor(Date.now() / 1000),
|
|
||||||
});
|
|
||||||
|
|
||||||
await relay.event(event);
|
|
||||||
|
|
||||||
setSubmitting(false);
|
|
||||||
setSubmitted(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
const username = useMemo(
|
|
||||||
() => n.bech32().safeParse(account?.acct).success ? account?.acct.slice(0, 13) : account?.acct,
|
|
||||||
[account?.acct],
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!account) {
|
|
||||||
return <ModalLoading />;
|
|
||||||
}
|
|
||||||
|
|
||||||
const acct = account.nostr.pubkey ? nip19.npubEncode(account.nostr.pubkey) : account.acct;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Modal
|
|
||||||
title={<FormattedMessage id='nostr_signin.account.title' defaultMessage='Your account' />}
|
|
||||||
onClose={onClose}
|
|
||||||
onBack={() => setStep('identity')}
|
|
||||||
>
|
|
||||||
<Stack space={6}>
|
|
||||||
<Stack space={3} alignItems='center'>
|
|
||||||
<Avatar className='bg-gray-100 dark:bg-gray-800' src={account.avatar} size={160} />
|
|
||||||
|
|
||||||
<Stack space={1}>
|
|
||||||
<Text
|
|
||||||
size='xl'
|
|
||||||
weight='semibold'
|
|
||||||
align='center'
|
|
||||||
dangerouslySetInnerHTML={{ __html: account.display_name_html }}
|
|
||||||
truncate
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Tooltip text={acct}>
|
|
||||||
<Text size='sm' theme='muted' align='center' truncate>
|
|
||||||
{username}
|
|
||||||
</Text>
|
|
||||||
</Tooltip>
|
|
||||||
</Stack>
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
{account.ditto.is_registered ? (
|
|
||||||
<Button theme='accent' size='lg' block>Continue</Button>
|
|
||||||
) : (
|
|
||||||
<Stack space={6}>
|
|
||||||
<Stack space={3} alignItems='center' className='rounded-xl bg-gray-100 p-4 dark:bg-gray-800'>
|
|
||||||
<Emoji className='h-16 w-16' emoji='🫂' />
|
|
||||||
|
|
||||||
<Text align='center' className='max-w-72'>
|
|
||||||
{(success || feedback) ? (
|
|
||||||
JSON.stringify(success || feedback, null, 2)
|
|
||||||
) : (
|
|
||||||
<>You need an account on {instance.title} to continue.</>
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
theme='accent'
|
|
||||||
size='lg'
|
|
||||||
onClick={handleJoin}
|
|
||||||
disabled={submitting || submitted}
|
|
||||||
block
|
|
||||||
>
|
|
||||||
Join
|
|
||||||
</Button>
|
|
||||||
</Stack>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
</Modal>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AccountStep;
|
|
|
@ -1,95 +0,0 @@
|
||||||
import React, { useState } from 'react';
|
|
||||||
import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
|
|
||||||
|
|
||||||
import { accountLookup } from 'soapbox/actions/accounts';
|
|
||||||
import { Button, Form, FormGroup, HStack, Input, Stack, Modal } from 'soapbox/components/ui';
|
|
||||||
import { useAppDispatch } from 'soapbox/hooks';
|
|
||||||
|
|
||||||
import EmojiGraphic from '../components/emoji-graphic';
|
|
||||||
import NostrExtensionIndicator from '../components/nostr-extension-indicator';
|
|
||||||
import { Step } from '../nostr-signin-modal';
|
|
||||||
|
|
||||||
interface IIdentityStep {
|
|
||||||
setAccountId(accountId: string): void;
|
|
||||||
setStep(step: Step): void;
|
|
||||||
onClose(): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
notFound: { id: 'nostr_signin.identity.not_found', defaultMessage: 'Account not found' },
|
|
||||||
nsec: { id: 'nostr_signin.identity.nsec', defaultMessage: 'Enter your public key' },
|
|
||||||
});
|
|
||||||
|
|
||||||
const IdentityStep: React.FC<IIdentityStep> = ({ setAccountId, setStep, onClose }) => {
|
|
||||||
const intl = useIntl();
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
|
|
||||||
const [error, setError] = useState<string>();
|
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
const [username, setUsername] = useState('');
|
|
||||||
|
|
||||||
const handleChangeUsername: React.ChangeEventHandler<HTMLInputElement> = (e) => {
|
|
||||||
setError(undefined);
|
|
||||||
setUsername(e.target.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
|
||||||
setLoading(true);
|
|
||||||
|
|
||||||
if (username.startsWith('nsec1')) {
|
|
||||||
setError(intl.formatMessage(messages.nsec));
|
|
||||||
setLoading(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const account = await dispatch(accountLookup(username));
|
|
||||||
setAccountId(account.id);
|
|
||||||
setStep('account');
|
|
||||||
} catch (e: any) {
|
|
||||||
if (e.response?.status === 404) {
|
|
||||||
setError(intl.formatMessage(messages.notFound));
|
|
||||||
}
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<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='🕵️' />
|
|
||||||
|
|
||||||
<FormGroup labelText='Username' errors={error ? [error] : []}>
|
|
||||||
<Input
|
|
||||||
icon={require('@tabler/icons/at.svg')}
|
|
||||||
placeholder='Username or npub'
|
|
||||||
value={username}
|
|
||||||
onChange={handleChangeUsername}
|
|
||||||
disabled={loading}
|
|
||||||
autoFocus
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
|
|
||||||
<HStack space={2} alignItems='center' justifyContent='between'>
|
|
||||||
<Button theme='transparent' onClick={() => setStep('key')} disabled={loading}>Sign up</Button>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
theme='accent'
|
|
||||||
type='submit' disabled={!username || loading || !!error}
|
|
||||||
onClick={handleSubmit}
|
|
||||||
>
|
|
||||||
Next
|
|
||||||
</Button>
|
|
||||||
</HStack>
|
|
||||||
</Stack>
|
|
||||||
</Form>
|
|
||||||
</Modal>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default IdentityStep;
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { getPublicKey, nip19 } from 'nostr-tools';
|
import { nip19 } from 'nostr-tools';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
@ -7,15 +7,12 @@ import { NKeys } from 'soapbox/features/nostr/keys';
|
||||||
|
|
||||||
import EmojiGraphic from '../components/emoji-graphic';
|
import EmojiGraphic from '../components/emoji-graphic';
|
||||||
import NostrExtensionIndicator from '../components/nostr-extension-indicator';
|
import NostrExtensionIndicator from '../components/nostr-extension-indicator';
|
||||||
import { Step } from '../nostr-signin-modal';
|
|
||||||
|
|
||||||
interface IKeyAddStep {
|
interface IKeyAddStep {
|
||||||
setAccountId(accountId: string): void;
|
|
||||||
setStep(step: Step): void;
|
|
||||||
onClose(): void;
|
onClose(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const KeyAddStep: React.FC<IKeyAddStep> = ({ setAccountId, setStep, onClose }) => {
|
const KeyAddStep: React.FC<IKeyAddStep> = ({ onClose }) => {
|
||||||
const [nsec, setNsec] = useState('');
|
const [nsec, setNsec] = useState('');
|
||||||
const [error, setError] = useState<string | undefined>();
|
const [error, setError] = useState<string | undefined>();
|
||||||
|
|
||||||
|
@ -29,10 +26,8 @@ const KeyAddStep: React.FC<IKeyAddStep> = ({ setAccountId, setStep, onClose }) =
|
||||||
const result = nip19.decode(nsec);
|
const result = nip19.decode(nsec);
|
||||||
if (result.type === 'nsec') {
|
if (result.type === 'nsec') {
|
||||||
const seckey = result.data;
|
const seckey = result.data;
|
||||||
const pubkey = getPublicKey(seckey);
|
|
||||||
NKeys.add(seckey);
|
NKeys.add(seckey);
|
||||||
setAccountId(pubkey);
|
// TODO: log in, close modal
|
||||||
setStep('account');
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setError('Invalid nsec');
|
setError('Invalid nsec');
|
||||||
|
|
|
@ -25,7 +25,7 @@ const KeyStep: React.FC<IKeyStep> = ({ setStep, onClose }) => {
|
||||||
Generate key
|
Generate key
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button theme='transparent' onClick={() => setStep('identity')}>
|
<Button theme='transparent' onClick={() => setStep('key-add')}>
|
||||||
I already have a key
|
I already have a key
|
||||||
</Button>
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
|
@ -11,15 +11,12 @@ import { download } from 'soapbox/utils/download';
|
||||||
import { slugify } from 'soapbox/utils/input';
|
import { slugify } from 'soapbox/utils/input';
|
||||||
|
|
||||||
import EmojiGraphic from '../components/emoji-graphic';
|
import EmojiGraphic from '../components/emoji-graphic';
|
||||||
import { Step } from '../nostr-signin-modal';
|
|
||||||
|
|
||||||
interface IKeygenStep {
|
interface IKeygenStep {
|
||||||
setAccountId(accountId: string): void;
|
|
||||||
setStep(step: Step): void;
|
|
||||||
onClose(): void;
|
onClose(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const KeygenStep: React.FC<IKeygenStep> = ({ setAccountId, setStep, onClose }) => {
|
const KeygenStep: React.FC<IKeygenStep> = ({ onClose }) => {
|
||||||
const instance = useInstance();
|
const instance = useInstance();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
@ -45,8 +42,7 @@ const KeygenStep: React.FC<IKeygenStep> = ({ setAccountId, setStep, onClose }) =
|
||||||
|
|
||||||
const handleNext = () => {
|
const handleNext = () => {
|
||||||
NKeys.add(secretKey);
|
NKeys.add(secretKey);
|
||||||
setAccountId(pubkey); // HACK: Ditto uses pubkeys as account IDs.
|
// TODO: log in, close modal
|
||||||
setStep('account');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
Loading…
Reference in New Issue