Fix signup flow skipping profile + recovery steps (1.3.16)

Root cause: the multi-step SignupDialog is hosted inside LoginArea, but
both the mobile header and the onboarding hero only rendered LoginArea
while logged OUT ({user ? menu : <LoginArea/>}). The signup flow logs the
user in at its FIRST step (to publish the profile), which flipped `user`
truthy and instantly UNMOUNTED LoginArea — destroying the dialog before
the profile and recovery steps could show. The skater was dumped on the
map with no recovery prompt (exactly the reported bug).

Fix: keep LoginArea mounted after login and merely hide its trigger
(dialog renders in a portal, so hiding the trigger is purely cosmetic).
MobileHeaderUserMenu / logged-in CTAs render alongside. The in-progress
signup now survives login and reaches the redesigned recovery step.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
This commit is contained in:
shakespeare.diy 2026-09-09 11:34:23 +07:00
parent 3cc3b623cc
commit aede706fd3
2 changed files with 27 additions and 14 deletions

View file

@ -708,17 +708,27 @@ export function Layout({ children, noPadding }: LayoutProps) {
<div className="flex items-center gap-1 flex-shrink-0">
{/* Notifications (crew invites & membership requests) */}
{user && <NotificationBell />}
{/* User menu when logged in / Login button when not */}
{user ? (
<MobileHeaderUserMenu
pubkey={user.pubkey}
{/* User menu when logged in / Login button when not.
IMPORTANT: LoginArea hosts the SignupDialog. The signup flow logs
the user in at the *first* step (to publish their profile), then
continues to the profile + recovery steps. If we unmount LoginArea
the instant `user` becomes truthy, the dialog is destroyed and the
skater is dumped on the map with no recovery step — the exact bug
reported. So we keep LoginArea mounted always and just hide its
trigger when logged in; MobileHeaderUserMenu becomes the visible
control. The dialog renders in a portal, so hiding the trigger is
purely cosmetic and never interrupts an in-progress signup. */}
{user && (
<MobileHeaderUserMenu
pubkey={user.pubkey}
onLogout={() => removeLogin(currentAccount?.id || '')}
onSetStatus={() => setShowStatusDialog(true)}
onAddAccount={() => setShowAddAccount(true)}
/>
) : (
<LoginArea compact className="flex flex-row gap-1" />
)}
<div className={cn(user && 'hidden')}>
<LoginArea compact className="flex flex-row gap-1" />
</div>
<Sheet open={mobileMenuOpen} onOpenChange={setMobileMenuOpen}>
<SheetTrigger asChild>

View file

@ -215,14 +215,17 @@ export default function OnboardingPage() {
<FeaturePill emoji="👥" label="Crews" />
</div>
{/* Primary CTA */}
{!user ? (
<div className="flex flex-col items-center gap-3">
<p className="text-sm text-gray-500 uppercase tracking-wider font-bold mb-1">Create your free account</p>
<LoginArea className="flex justify-center" />
<p className="text-xs text-gray-600 mt-2">No email. No password. Own your identity forever.</p>
</div>
) : (
{/* Primary CTA.
LoginArea (which hosts the multi-step SignupDialog) is kept mounted
even after login and merely hidden — otherwise logging in at the
first signup step would unmount the dialog and skip the profile +
recovery steps. */}
<div className={cn('flex-col items-center gap-3', user ? 'hidden' : 'flex')}>
<p className="text-sm text-gray-500 uppercase tracking-wider font-bold mb-1">Create your free account</p>
<LoginArea className="flex justify-center" />
<p className="text-xs text-gray-600 mt-2">No email. No password. Own your identity forever.</p>
</div>
{user && (
<div className="flex flex-wrap gap-3 justify-center">
<Link to="/map">
<Button size="lg" className="bg-[#ff0040] hover:bg-[#ff0040]/90 gap-2 font-black uppercase shadow-[0_0_30px_rgba(255,0,64,0.3)]">