From a4be895670cf46c45c4ac38dfcf9e51c9f827478 Mon Sep 17 00:00:00 2001 From: Jannis Braun <151788261+TheZwiss@users.noreply.github.com> Date: Fri, 13 Mar 2026 03:26:32 +0100 Subject: [PATCH] fix: JoinPage identity card + equal-weight other-instance option Add avatar/name/username identity card in the federation connect phase so users can confirm their account before entering their password. Promote "I use another instance" from a hidden
collapsible to an equal-weight button with an "or" divider, using a dedicated 'other-instance' phase with Back navigation. --- packages/web/src/components/JoinPage.tsx | 113 ++++++++++++++++------- 1 file changed, 78 insertions(+), 35 deletions(-) diff --git a/packages/web/src/components/JoinPage.tsx b/packages/web/src/components/JoinPage.tsx index 1238e368..1689414d 100644 --- a/packages/web/src/components/JoinPage.tsx +++ b/packages/web/src/components/JoinPage.tsx @@ -15,10 +15,20 @@ export function JoinPage() { const navigate = useNavigate(); const token = useAuthStore((s) => s.token); const user = useAuthStore((s) => s.user); + const loadUser = useAuthStore((s) => s.loadUser); + const isAuthLoading = useAuthStore((s) => s.isLoading); const joinByCode = useSpaceStore((s) => s.joinByCode); const connectToRemote = useInstanceStore((s) => s.connectToRemote); const loginToRemote = useInstanceStore((s) => s.loginToRemote); + // Hydrate auth store when token exists — useAuth() can't be used here because + // it hard-redirects to /login when there's no token, and JoinPage is a public route. + useEffect(() => { + if (token && !user && !isAuthLoading) { + loadUser(); + } + }, [token, user, isAuthLoading, loadUser]); + const [preview, setPreview] = useState(null); const [previewError, setPreviewError] = useState(''); const [isLoadingPreview, setIsLoadingPreview] = useState(true); @@ -257,10 +267,10 @@ export function JoinPage() { /* Authenticated user */ ) : ( /* Unauthenticated user */ @@ -277,47 +287,80 @@ export function JoinPage() { > Create an account + + {/* Divider */} +
+
+ or +
+
+ +
)} - - {/* Other instance section */} -
- - I use Backspace on another instance - -
- -
- setOtherDomain(e.target.value)} - placeholder="e.g. my-instance.com" - className="flex-1 px-3 py-2 bg-surface-input rounded text-txt-primary text-sm outline-none focus:ring-2 focus:ring-accent-primary" - /> - -
-

- You'll be redirected to your home instance to complete joining. -

-
-
)} + {/* Phase: other-instance — domain input for federation redirect */} + {phase === 'other-instance' && ( +
+ +
+ setOtherDomain(e.target.value)} + placeholder="e.g. my-instance.com" + className="flex-1 px-3 py-2 bg-surface-input rounded text-txt-primary text-sm outline-none focus:ring-2 focus:ring-accent-primary" + autoFocus + /> + +
+

+ You'll be redirected to your home instance to complete joining. +

+ +
+ )} + {/* Phase: connect — password prompt for federation */} {phase === 'connect' && (
-

- Connect to {hostDisplay} to join this space. + {/* Identity card */} +

+ +
+

{user?.displayName || user?.username}

+

@{user?.username}

+
+
+

+ Connecting to {hostDisplay}