From 2917c034edb126de2268cb8d3581204e622a70f7 Mon Sep 17 00:00:00 2001 From: 3dtours Date: Fri, 18 Sep 2026 08:02:57 +0700 Subject: [PATCH] Sign in is the default: the landing names the account, and an admin lands on /admin --- docker/frontend/src/App.tsx | 11 +++--- docker/frontend/src/Landing.tsx | 63 +++++++++++++++++++++++---------- 2 files changed, 52 insertions(+), 22 deletions(-) diff --git a/docker/frontend/src/App.tsx b/docker/frontend/src/App.tsx index 05d9808..5f08330 100644 --- a/docker/frontend/src/App.tsx +++ b/docker/frontend/src/App.tsx @@ -290,10 +290,13 @@ export function Workspace() { // Recipes made in this session, guest ones included. A guest's copy lives // here and nowhere else, so reloading the page is what deletes it. const [created, setCreated] = useState([]); - // null = closed. /app?auth=1 opens the studio's dialog straight on the sign-up - // tab; the landing page runs the same dialog in place instead of linking here. - const [authMode, setAuthMode] = useState<'login' | 'signup' | null>(() => - (new URLSearchParams(window.location.search).has('auth') ? 'signup' : null)); + // null = closed. /app?auth=1 opens the studio's dialog straight on the sign-in + // tab (sign-in is the default; ?auth=signup asks for the other one); the + // landing page runs the same dialog in place instead of linking here. + const [authMode, setAuthMode] = useState<'login' | 'signup' | null>(() => { + const asked = new URLSearchParams(window.location.search).get('auth'); + return asked ? (asked === 'signup' ? 'signup' : 'login') : null; + }); const renderToken = useRef(0); // Which previewMax the bytes in previewBytes were made at, so the upgrade diff --git a/docker/frontend/src/Landing.tsx b/docker/frontend/src/Landing.tsx index 11b3a6f..7cc3d9f 100644 --- a/docker/frontend/src/Landing.tsx +++ b/docker/frontend/src/Landing.tsx @@ -117,7 +117,7 @@ export function Landing() { // studio: the visitor keeps their scroll position and lands back on the reel. const [auth, setAuth] = useState<'login' | 'signup' | null>(() => { const asked = new URLSearchParams(window.location.search).get('auth'); - return asked === 'login' ? 'login' : asked ? 'signup' : null; + return asked === 'signup' ? 'signup' : asked ? 'login' : null; }); const [uploading, setUploading] = useState(false); const filePick = useRef(null); @@ -138,11 +138,16 @@ export function Landing() { // The community half of the reel: whoever is signed in gets a picker, and // everybody sees the result on the next load. A guest is sent to sign up. const reload = useCallback(() => { - api.me().then((r) => setUser(r.user)).catch(() => undefined); api.listPhotos().then((r) => setPhotos(r.photos)).catch(() => undefined); + return api.me().then((r) => { + setUser(r.user); + return r.user; + }).catch(() => null); }, []); - useEffect(reload, [reload]); + useEffect(() => { + reload(); + }, [reload]); const contribute = useCallback(async (file: File) => { setUploading(true); @@ -284,10 +289,24 @@ export function Landing() { {lang.toUpperCase()} - {/* Register: the dialog opens here, on the page the visitor is on. */} - + {/* Sign in is the default: the dialog opens here, on the page the + visitor is on, and flips to sign-up from its own toggle. Once + signed in the same slot names the account, so the session is + visible on the page that took the credentials. */} + {user ? ( + + {user.email.split('@')[0]} + + ) : ( + + )} @@ -299,14 +318,20 @@ export function Landing() {
{nav.map((entry) => setMenu(false)}>{c(entry.label)})} setMenu(false)}>{c({ en: 'Open studio', vi: 'Mở studio' })} - + {user ? ( + setMenu(false)}> + {user.email.split('@')[0]} + + ) : ( + + )} )} @@ -670,7 +695,9 @@ export function Landing() { onClose={() => setAuth(null)} onDone={() => { setAuth(null); - reload(); + // An admin signs in here to moderate, so send them on to the page + // that asked for the session in the first place. + reload().then((u) => u?.admin && window.location.assign('/admin')); }} /> ) : null}