mirror of
https://gitlab.com/soapbox-pub/mkstack.git
synced 2025-09-24 02:06:07 +00:00
Refactor SignupDialog to match Soapbox design with improved UX
- Simplify SignupDialog UI to clean Soapbox-style layout with key emoji - Fix button width to match text size instead of full width - Implement proper key generation flow using existing generateSecretKey code - Replace toast message with direct login modal opening for 'I already have a key' - Remove duplicate NostrExtensionIndicator (LoginDialog already handles extensions) - Update LoginArea to handle modal transitions between signup and login - Maintain 3-step flow: key selection → generation → confirmation - Reuse existing MKStack functionality instead of reinventing wheel
This commit is contained in:
parent
05c0ec92f7
commit
a0bd6729ae
@ -58,6 +58,10 @@ export function LoginArea({ className }: LoginAreaProps) {
|
||||
isOpen={signupDialogOpen}
|
||||
onClose={() => setSignupDialogOpen(false)}
|
||||
onLogin={handleLogin}
|
||||
onOpenLogin={() => {
|
||||
setSignupDialogOpen(false);
|
||||
setLoginDialogOpen(true);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,50 +0,0 @@
|
||||
import React from 'react';
|
||||
import { useLoginActions } from '@/hooks/useLoginActions';
|
||||
|
||||
interface NostrExtensionIndicatorProps {
|
||||
onLogin?: () => void;
|
||||
onClose?: () => void;
|
||||
}
|
||||
|
||||
const NostrExtensionIndicator: React.FC<NostrExtensionIndicatorProps> = ({ onLogin, onClose }) => {
|
||||
const login = useLoginActions();
|
||||
|
||||
const handleExtensionLogin = async () => {
|
||||
try {
|
||||
await login.extension();
|
||||
onLogin?.();
|
||||
onClose?.();
|
||||
} catch (error) {
|
||||
console.error('Extension login failed:', error);
|
||||
}
|
||||
};
|
||||
|
||||
function renderBody(): React.ReactNode {
|
||||
if ('nostr' in window) {
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
type='button'
|
||||
className='underline text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300'
|
||||
onClick={handleExtensionLogin}
|
||||
>
|
||||
Sign in
|
||||
</button>
|
||||
{' '}with browser extension.
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return 'Browser extension not found.';
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='flex items-center rounded-lg bg-gray-100 p-3 dark:bg-gray-800'>
|
||||
<p className='text-xs text-gray-600 dark:text-gray-400'>
|
||||
{renderBody()}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default NostrExtensionIndicator;
|
@ -2,13 +2,12 @@
|
||||
// It is important that all functionality in this file is preserved, and should only be modified if explicitly requested.
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
|
||||
|
||||
import { toast } from '@/hooks/useToast';
|
||||
import { useLoginActions } from '@/hooks/useLoginActions';
|
||||
import { generateSecretKey, nip19 } from 'nostr-tools';
|
||||
|
||||
import NostrExtensionIndicator from './NostrExtensionIndicator';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
interface SignupDialogProps {
|
||||
@ -16,36 +15,76 @@ interface SignupDialogProps {
|
||||
onClose: () => void;
|
||||
onComplete?: () => void;
|
||||
onLogin?: () => void;
|
||||
onOpenLogin?: () => void;
|
||||
}
|
||||
|
||||
const SignupDialog: React.FC<SignupDialogProps> = ({ isOpen, onClose, onLogin }) => {
|
||||
const [step, setStep] = useState<'key' | 'keygen'>('key');
|
||||
const SignupDialog: React.FC<SignupDialogProps> = ({ isOpen, onClose, onLogin, onOpenLogin }) => {
|
||||
const [step, setStep] = useState<'key' | 'keygen' | 'download'>('key');
|
||||
const [nsec, setNsec] = useState('');
|
||||
const login = useLoginActions();
|
||||
|
||||
const handleGenerateKey = () => {
|
||||
setStep('keygen');
|
||||
|
||||
// Add a dramatic pause for the key generation effect
|
||||
setTimeout(() => {
|
||||
try {
|
||||
// Generate a new secret key
|
||||
const sk = generateSecretKey();
|
||||
|
||||
// Convert to nsec format
|
||||
setNsec(nip19.nsecEncode(sk));
|
||||
setStep('download');
|
||||
|
||||
toast({
|
||||
title: 'Your Secret Key is Ready!',
|
||||
description: 'A new secret key has been generated for you.',
|
||||
});
|
||||
} catch {
|
||||
toast({
|
||||
title: 'Error',
|
||||
description: 'Failed to generate key. Please try again.',
|
||||
variant: 'destructive',
|
||||
});
|
||||
setStep('key');
|
||||
}
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
const handleHasKey = () => {
|
||||
onClose();
|
||||
// This would trigger the login dialog to open with the key-add step
|
||||
// For now, we'll just show a toast message
|
||||
toast({
|
||||
title: 'Use Login Instead',
|
||||
description: 'Please use the login dialog to enter your existing key.',
|
||||
});
|
||||
if (onOpenLogin) {
|
||||
onOpenLogin();
|
||||
}
|
||||
};
|
||||
|
||||
const handleExtensionLogin = () => {
|
||||
const handleUseKey = () => {
|
||||
try {
|
||||
login.nsec(nsec);
|
||||
if (onLogin) {
|
||||
onLogin();
|
||||
}
|
||||
onClose();
|
||||
toast({
|
||||
title: 'Welcome!',
|
||||
description: 'Your account is ready.',
|
||||
});
|
||||
} catch {
|
||||
toast({
|
||||
title: 'Login Failed',
|
||||
description: 'Failed to login with the generated key. Please try again.',
|
||||
variant: 'destructive',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Reset state when dialog opens
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
setStep('key');
|
||||
setNsec('');
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
@ -73,7 +112,7 @@ const SignupDialog: React.FC<SignupDialogProps> = ({ isOpen, onClose, onLogin })
|
||||
|
||||
<div className='flex flex-col items-center space-y-3 w-full'>
|
||||
<Button
|
||||
className='w-full bg-blue-600 hover:bg-blue-700 text-white font-medium py-3 px-6 rounded-lg'
|
||||
className='bg-blue-600 hover:bg-blue-700 text-white font-medium py-3 px-6 rounded-lg'
|
||||
size='lg'
|
||||
onClick={handleGenerateKey}
|
||||
>
|
||||
@ -95,13 +134,41 @@ const SignupDialog: React.FC<SignupDialogProps> = ({ isOpen, onClose, onLogin })
|
||||
<div className='text-center space-y-4'>
|
||||
<div className='space-y-2'>
|
||||
<p className='text-lg font-semibold'>
|
||||
Key Generation Coming Soon
|
||||
Generating your secret key...
|
||||
</p>
|
||||
<p className='text-sm text-muted-foreground'>
|
||||
Key generation feature is being developed. For now, please use an existing key or browser extension.
|
||||
Creating your secure key
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className='flex justify-center'>
|
||||
<div className='w-8 h-8 border-4 border-blue-600 border-t-transparent rounded-full animate-spin'></div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{step === 'download' && (
|
||||
<div className='text-center space-y-4'>
|
||||
<div className='space-y-2'>
|
||||
<p className='text-lg font-semibold'>
|
||||
Your secret key has been generated!
|
||||
</p>
|
||||
<p className='text-sm text-muted-foreground'>
|
||||
Your key is ready to use.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className='text-6xl'>
|
||||
✅
|
||||
</div>
|
||||
|
||||
<Button
|
||||
className='w-full bg-blue-600 hover:bg-blue-700 text-white font-medium py-3 px-6 rounded-lg'
|
||||
onClick={handleUseKey}
|
||||
>
|
||||
Continue with generated key
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant='outline'
|
||||
onClick={() => setStep('key')}
|
||||
@ -112,23 +179,7 @@ const SignupDialog: React.FC<SignupDialogProps> = ({ isOpen, onClose, onLogin })
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className='space-y-4'>
|
||||
<div className='relative'>
|
||||
<div className='absolute inset-0 flex items-center'>
|
||||
<div className='w-full border-t border-gray-300 dark:border-gray-600'></div>
|
||||
</div>
|
||||
<div className='relative flex justify-center text-sm'>
|
||||
<span className='px-3 bg-background text-muted-foreground'>
|
||||
or
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<NostrExtensionIndicator
|
||||
onLogin={handleExtensionLogin}
|
||||
onClose={onClose}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
Loading…
x
Reference in New Issue
Block a user