NostrSigninModal: make each step render a Modal directly
This commit is contained in:
parent
9267ef28e3
commit
ba04c43477
6 changed files with 135 additions and 147 deletions
|
@ -1,7 +1,4 @@
|
|||
import React, { useState } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { Modal, Stack } from 'soapbox/components/ui';
|
||||
|
||||
import AccountStep from './steps/account-step';
|
||||
import ExtensionStep from './steps/extension-step';
|
||||
|
@ -18,50 +15,22 @@ const NostrSigninModal: React.FC<INostrSigninModal> = ({ onClose }) => {
|
|||
|
||||
const [accountId, setAccountId] = useState<string | undefined>();
|
||||
|
||||
const handleClose = () => {
|
||||
onClose('NOSTR_SIGNIN');
|
||||
};
|
||||
const handleClose = () => onClose('NOSTR_SIGNIN');
|
||||
|
||||
const renderStep = () => {
|
||||
switch (step) {
|
||||
case 0:
|
||||
return <ExtensionStep setStep={setStep} />;
|
||||
case 1:
|
||||
return <IdentityStep setAccountId={setAccountId} setStep={setStep} />;
|
||||
case 2:
|
||||
return <KeyStep setStep={setStep} />;
|
||||
case 3:
|
||||
return <AccountStep accountId={accountId!} />;
|
||||
case 4:
|
||||
return <RegisterStep />;
|
||||
}
|
||||
};
|
||||
|
||||
const renderModalTitle = () => {
|
||||
switch (step) {
|
||||
case 0:
|
||||
return <FormattedMessage id='nostr_signin.siwe.title' defaultMessage='Sign in' />;
|
||||
case 1:
|
||||
return <FormattedMessage id='nostr_signin.identity.title' defaultMessage='Who are you?' />;
|
||||
case 2:
|
||||
return <FormattedMessage id='nostr_signin.key.title' defaultMessage='You need a key to continue' />;
|
||||
case 3:
|
||||
return <FormattedMessage id='nostr_signin.account.title' defaultMessage='Create an account' />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={renderModalTitle()}
|
||||
onClose={handleClose}
|
||||
>
|
||||
<Stack space={2}>
|
||||
{renderStep()}
|
||||
</Stack>
|
||||
</Modal>
|
||||
);
|
||||
switch (step) {
|
||||
case 0:
|
||||
return <ExtensionStep setStep={setStep} onClose={handleClose} />;
|
||||
case 1:
|
||||
return <IdentityStep setAccountId={setAccountId} setStep={setStep} onClose={handleClose} />;
|
||||
case 2:
|
||||
return <KeyStep setStep={setStep} onClose={handleClose} />;
|
||||
case 3:
|
||||
return <AccountStep accountId={accountId!} setStep={setStep} onClose={handleClose} />;
|
||||
case 4:
|
||||
return <RegisterStep onClose={handleClose} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export default NostrSigninModal;
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
import { NSchema as n } from 'nspec';
|
||||
import React, { useMemo } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { useAccount } from 'soapbox/api/hooks';
|
||||
import { Avatar, Text, Stack, Emoji, Button, Tooltip } from 'soapbox/components/ui';
|
||||
import { Avatar, Text, Stack, Emoji, Button, Tooltip, HStack, Modal } from 'soapbox/components/ui';
|
||||
import { useInstance } from 'soapbox/hooks';
|
||||
|
||||
interface IAccountStep {
|
||||
accountId: string;
|
||||
setStep(step: number): void;
|
||||
onClose(): void;
|
||||
}
|
||||
|
||||
const AccountStep: React.FC<IAccountStep> = ({ accountId }) => {
|
||||
const AccountStep: React.FC<IAccountStep> = ({ accountId, setStep, onClose }) => {
|
||||
const { account } = useAccount(accountId);
|
||||
const instance = useInstance();
|
||||
|
||||
|
@ -18,50 +21,58 @@ const AccountStep: React.FC<IAccountStep> = ({ accountId }) => {
|
|||
[account?.acct],
|
||||
);
|
||||
|
||||
const goBack = () => setStep(1);
|
||||
|
||||
if (!account) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack space={6}>
|
||||
<Stack space={3} alignItems='center'>
|
||||
<Avatar className='bg-gray-100 dark:bg-gray-800' src={account.avatar} size={160} />
|
||||
<Modal title={<FormattedMessage id='nostr_signin.account.title' defaultMessage='Your account' />} onClose={onClose}>
|
||||
<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
|
||||
/>
|
||||
<Stack space={1}>
|
||||
<Text
|
||||
size='xl'
|
||||
weight='semibold'
|
||||
align='center'
|
||||
dangerouslySetInnerHTML={{ __html: account.display_name_html }}
|
||||
truncate
|
||||
/>
|
||||
|
||||
<Tooltip text={account.nostr.npub ?? account.acct}>
|
||||
<Text size='sm' theme='muted' align='center' truncate>
|
||||
{isBech32 ? (
|
||||
account.acct.slice(0, 13)
|
||||
) : (
|
||||
account.acct
|
||||
)}
|
||||
</Text>
|
||||
</Tooltip>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
{!account.ditto.is_registered && (
|
||||
<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'>
|
||||
You need an account on {instance.title} to continue.
|
||||
</Text>
|
||||
<Tooltip text={account.nostr.npub ?? account.acct}>
|
||||
<Text size='sm' theme='muted' align='center' truncate>
|
||||
{isBech32 ? account.acct.slice(0, 13) : account.acct}
|
||||
</Text>
|
||||
</Tooltip>
|
||||
</Stack>
|
||||
|
||||
<Button theme='accent' size='lg'>Join</Button>
|
||||
</Stack>
|
||||
)}
|
||||
</Stack>
|
||||
|
||||
{account.ditto.is_registered ? (
|
||||
<HStack space={3}>
|
||||
<Button theme='transparent' size='lg' block onClick={goBack}>Not me</Button>
|
||||
<Button theme='accent' size='lg' block>Continue</Button>
|
||||
</HStack>
|
||||
) : (
|
||||
<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'>
|
||||
You need an account on {instance.title} to continue.
|
||||
</Text>
|
||||
</Stack>
|
||||
|
||||
<HStack space={3}>
|
||||
<Button theme='transparent' size='lg' block onClick={goBack}>Not me</Button>
|
||||
<Button theme='accent' size='lg' block>Join</Button>
|
||||
</HStack>
|
||||
</Stack>
|
||||
)}
|
||||
</Stack>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -2,34 +2,36 @@ import React from 'react';
|
|||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { nostrExtensionLogIn } from 'soapbox/actions/nostr';
|
||||
import Button from 'soapbox/components/ui/button/button';
|
||||
import Stack from 'soapbox/components/ui/stack/stack';
|
||||
import { Button, Stack, Modal } from 'soapbox/components/ui';
|
||||
import { useAppDispatch } from 'soapbox/hooks';
|
||||
|
||||
import EmojiGraphic from '../components/emoji-graphic';
|
||||
|
||||
interface IExtensionStep {
|
||||
setStep: (step: number) => void;
|
||||
onClose(): void;
|
||||
}
|
||||
|
||||
const ExtensionStep: React.FC<IExtensionStep> = ({ setStep }) => {
|
||||
const ExtensionStep: React.FC<IExtensionStep> = ({ setStep, onClose }) => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const onClick = () => dispatch(nostrExtensionLogIn());
|
||||
const onClickAlt = () => setStep(1);
|
||||
|
||||
return (
|
||||
<Stack className='my-6' space={3}>
|
||||
<EmojiGraphic emoji='🔐' />
|
||||
<Modal title={<FormattedMessage id='nostr_signin.siwe.title' defaultMessage='Sign in' />} onClose={onClose}>
|
||||
<Stack className='my-6' space={3}>
|
||||
<EmojiGraphic emoji='🔐' />
|
||||
|
||||
<Button theme='accent' size='lg' onClick={onClick}>
|
||||
<FormattedMessage id='nostr_signin.siwe.action' defaultMessage='Sign in with extension' />
|
||||
</Button>
|
||||
<Button theme='accent' size='lg' onClick={onClick}>
|
||||
<FormattedMessage id='nostr_signin.siwe.action' defaultMessage='Sign in with extension' />
|
||||
</Button>
|
||||
|
||||
<Button theme='transparent' onClick={onClickAlt}>
|
||||
<FormattedMessage id='nostr_signin.siwe.alt' defaultMessage='Sign in with key' />
|
||||
</Button>
|
||||
</Stack>
|
||||
<Button theme='transparent' onClick={onClickAlt}>
|
||||
<FormattedMessage id='nostr_signin.siwe.alt' defaultMessage='Sign in with key' />
|
||||
</Button>
|
||||
</Stack>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
import React, { useState } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { accountLookup } from 'soapbox/actions/accounts';
|
||||
import Button from 'soapbox/components/ui/button/button';
|
||||
import Form from 'soapbox/components/ui/form/form';
|
||||
import FormGroup from 'soapbox/components/ui/form-group/form-group';
|
||||
import HStack from 'soapbox/components/ui/hstack/hstack';
|
||||
import Input from 'soapbox/components/ui/input/input';
|
||||
import Stack from 'soapbox/components/ui/stack/stack';
|
||||
import { Button, Form, FormGroup, HStack, Input, Stack, Modal } from 'soapbox/components/ui';
|
||||
import { useAppDispatch } from 'soapbox/hooks';
|
||||
|
||||
import EmojiGraphic from '../components/emoji-graphic';
|
||||
|
@ -15,9 +11,10 @@ import NostrExtensionIndicator from '../components/nostr-extension-indicator';
|
|||
interface IIdentityStep {
|
||||
setAccountId(accountId: string): void;
|
||||
setStep(step: number): void;
|
||||
onClose(): void;
|
||||
}
|
||||
|
||||
const IdentityStep: React.FC<IIdentityStep> = ({ setAccountId, setStep }) => {
|
||||
const IdentityStep: React.FC<IIdentityStep> = ({ setAccountId, setStep, onClose }) => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
@ -53,36 +50,38 @@ const IdentityStep: React.FC<IIdentityStep> = ({ setAccountId, setStep }) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<Form>
|
||||
<Stack className='mt-3' space={3}>
|
||||
<NostrExtensionIndicator />
|
||||
<Modal title={<FormattedMessage id='nostr_signin.identity.title' defaultMessage='Who are you?' />} onClose={onClose}>
|
||||
<Form>
|
||||
<Stack className='mt-3' space={3}>
|
||||
<NostrExtensionIndicator />
|
||||
|
||||
<EmojiGraphic emoji='🕵️' />
|
||||
<EmojiGraphic emoji='🕵️' />
|
||||
|
||||
<FormGroup labelText='Username' errors={errors}>
|
||||
<Input
|
||||
icon={require('@tabler/icons/at.svg')}
|
||||
placeholder='Username or npub'
|
||||
value={username}
|
||||
onChange={handleChangeUsername}
|
||||
disabled={loading}
|
||||
autoFocus
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup labelText='Username' errors={errors}>
|
||||
<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(2)} disabled={loading}>Sign up</Button>
|
||||
<HStack space={2} alignItems='center' justifyContent='between'>
|
||||
<Button theme='transparent' onClick={() => setStep(2)} disabled={loading}>Sign up</Button>
|
||||
|
||||
<Button
|
||||
theme='accent'
|
||||
type='submit' disabled={!username || loading || notFound}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
Next
|
||||
</Button>
|
||||
</HStack>
|
||||
</Stack>
|
||||
</Form>
|
||||
<Button
|
||||
theme='accent'
|
||||
type='submit' disabled={!username || loading || notFound}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
Next
|
||||
</Button>
|
||||
</HStack>
|
||||
</Stack>
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,32 +1,35 @@
|
|||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import Button from 'soapbox/components/ui/button/button';
|
||||
import Stack from 'soapbox/components/ui/stack/stack';
|
||||
import { Button, Stack, Modal } from 'soapbox/components/ui';
|
||||
|
||||
import EmojiGraphic from '../components/emoji-graphic';
|
||||
import NostrExtensionIndicator from '../components/nostr-extension-indicator';
|
||||
|
||||
interface IKeyStep {
|
||||
setStep(step: number): void;
|
||||
onClose(): void;
|
||||
}
|
||||
|
||||
const KeyStep: React.FC<IKeyStep> = ({ setStep }) => {
|
||||
const KeyStep: React.FC<IKeyStep> = ({ setStep, onClose }) => {
|
||||
return (
|
||||
<Stack className='my-3' space={6} justifyContent='center'>
|
||||
<NostrExtensionIndicator />
|
||||
<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'>
|
||||
<NostrExtensionIndicator />
|
||||
|
||||
<EmojiGraphic emoji='🔑' />
|
||||
<EmojiGraphic emoji='🔑' />
|
||||
|
||||
<Stack space={3} alignItems='center'>
|
||||
<Button theme='accent' size='lg'>
|
||||
Generate key
|
||||
</Button>
|
||||
<Stack space={3} alignItems='center'>
|
||||
<Button theme='accent' size='lg'>
|
||||
Generate key
|
||||
</Button>
|
||||
|
||||
<Button theme='transparent' onClick={() => setStep(1)}>
|
||||
I already have a key
|
||||
</Button>
|
||||
<Button theme='transparent' onClick={() => setStep(1)}>
|
||||
I already have a key
|
||||
</Button>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import Stack from 'soapbox/components/ui/stack/stack';
|
||||
import { Stack, Modal } from 'soapbox/components/ui';
|
||||
|
||||
interface IRegisterStep {
|
||||
onClose(): void;
|
||||
}
|
||||
|
||||
const RegisterStep: React.FC<IRegisterStep> = () => {
|
||||
const RegisterStep: React.FC<IRegisterStep> = ({ onClose }) => {
|
||||
return (
|
||||
<Stack space={3}>
|
||||
register step
|
||||
</Stack>
|
||||
<Modal title={<FormattedMessage id='nostr_signin.register.title' defaultMessage='Create account' />} onClose={onClose}>
|
||||
<Stack space={3}>
|
||||
register step
|
||||
</Stack>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue