akseljoonas HF Staff commited on
Commit
bdb3c28
Β·
1 Parent(s): 659c746

fix: auto-detect org membership via localStorage, remove manual button

Browse files

Use visibilitychange event to auto-advance after user returns from
the join link. Persist org-joined state in localStorage so returning
users skip the join screen entirely.

frontend/src/components/WelcomeScreen/WelcomeScreen.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import { useState, useCallback } from 'react';
2
  import {
3
  Box,
4
  Typography,
@@ -17,18 +17,41 @@ import { isInIframe, triggerLogin } from '@/hooks/useAuth';
17
  const HF_ORANGE = '#FF9D00';
18
 
19
  const ORG_JOIN_URL = 'https://huggingface.co/organizations/ml-agent-explorers/share/GzPMJUivoFPlfkvFtIqEouZKSytatKQSZT';
 
 
 
 
 
 
 
 
 
20
 
21
  export default function WelcomeScreen() {
22
  const { createSession } = useSessionStore();
23
  const { setPlan, clearPanel, user } = useAgentStore();
24
  const [isCreating, setIsCreating] = useState(false);
25
  const [error, setError] = useState<string | null>(null);
26
- const [iframeJoined, setIframeJoined] = useState(false);
 
27
 
28
  const inIframe = isInIframe();
29
  const isAuthenticated = user?.authenticated;
30
  const isDevUser = user?.username === 'dev';
31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  const tryCreateSession = useCallback(async () => {
33
  setIsCreating(true);
34
  setError(null);
@@ -96,6 +119,34 @@ export default function WelcomeScreen() {
96
  },
97
  };
98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  return (
100
  <Box
101
  sx={{
@@ -131,8 +182,8 @@ export default function WelcomeScreen() {
131
  HF Agent
132
  </Typography>
133
 
134
- {/* ── Iframe: join org β†’ then redirect to Space ────────────── */}
135
- {inIframe && !iframeJoined && (
136
  <>
137
  <Typography
138
  variant="body1"
@@ -157,51 +208,19 @@ export default function WelcomeScreen() {
157
  href={ORG_JOIN_URL}
158
  target="_blank"
159
  rel="noopener noreferrer"
 
160
  startIcon={<GroupAddIcon />}
161
  sx={primaryBtnSx}
162
  >
163
  Join ML Agent Explorers
164
  </Button>
165
-
166
- <Button
167
- variant="text"
168
- size="small"
169
- onClick={() => setIframeJoined(true)}
170
- sx={{
171
- mt: 2,
172
- color: 'var(--muted-text)',
173
- textTransform: 'none',
174
- fontSize: '0.85rem',
175
- '&:hover': { color: 'var(--text)' },
176
- }}
177
- >
178
- I've already joined β†’
179
- </Button>
180
  </>
181
  )}
182
 
183
- {/* ── Iframe: after joining β†’ open Space ───────────────────── */}
184
- {inIframe && iframeJoined && (
185
  <>
186
- <Typography
187
- variant="body1"
188
- sx={{
189
- color: 'var(--muted-text)',
190
- maxWidth: 520,
191
- mb: 5,
192
- lineHeight: 1.8,
193
- fontSize: '0.95rem',
194
- textAlign: 'center',
195
- px: 2,
196
- '& strong': { color: 'var(--text)', fontWeight: 600 },
197
- }}
198
- >
199
- A general-purpose AI agent for <strong>machine learning engineering</strong>.
200
- It browses <strong>Hugging Face documentation</strong>, manages{' '}
201
- <strong>repositories</strong>, launches <strong>training jobs</strong>,
202
- and explores <strong>datasets</strong> β€” all through natural conversation.
203
- </Typography>
204
-
205
  <Button
206
  variant="contained"
207
  size="large"
@@ -218,27 +237,9 @@ export default function WelcomeScreen() {
218
  )}
219
 
220
  {/* ── Direct: not logged in β†’ sign in ──────────────────────── */}
221
- {!inIframe && !isAuthenticated && !isDevUser && (
222
  <>
223
- <Typography
224
- variant="body1"
225
- sx={{
226
- color: 'var(--muted-text)',
227
- maxWidth: 520,
228
- mb: 5,
229
- lineHeight: 1.8,
230
- fontSize: '0.95rem',
231
- textAlign: 'center',
232
- px: 2,
233
- '& strong': { color: 'var(--text)', fontWeight: 600 },
234
- }}
235
- >
236
- A general-purpose AI agent for <strong>machine learning engineering</strong>.
237
- It browses <strong>Hugging Face documentation</strong>, manages{' '}
238
- <strong>repositories</strong>, launches <strong>training jobs</strong>,
239
- and explores <strong>datasets</strong> β€” all through natural conversation.
240
- </Typography>
241
-
242
  <Button
243
  variant="contained"
244
  size="large"
@@ -265,27 +266,9 @@ export default function WelcomeScreen() {
265
  )}
266
 
267
  {/* ── Direct: authenticated β†’ start session ────────────────── */}
268
- {!inIframe && (isAuthenticated || isDevUser) && (
269
  <>
270
- <Typography
271
- variant="body1"
272
- sx={{
273
- color: 'var(--muted-text)',
274
- maxWidth: 520,
275
- mb: 5,
276
- lineHeight: 1.8,
277
- fontSize: '0.95rem',
278
- textAlign: 'center',
279
- px: 2,
280
- '& strong': { color: 'var(--text)', fontWeight: 600 },
281
- }}
282
- >
283
- A general-purpose AI agent for <strong>machine learning engineering</strong>.
284
- It browses <strong>Hugging Face documentation</strong>, manages{' '}
285
- <strong>repositories</strong>, launches <strong>training jobs</strong>,
286
- and explores <strong>datasets</strong> β€” all through natural conversation.
287
- </Typography>
288
-
289
  <Button
290
  variant="contained"
291
  size="large"
 
1
+ import { useState, useCallback, useEffect, useRef } from 'react';
2
  import {
3
  Box,
4
  Typography,
 
17
  const HF_ORANGE = '#FF9D00';
18
 
19
  const ORG_JOIN_URL = 'https://huggingface.co/organizations/ml-agent-explorers/share/GzPMJUivoFPlfkvFtIqEouZKSytatKQSZT';
20
+ const ORG_JOINED_KEY = 'hf-agent-org-joined';
21
+
22
+ function hasJoinedOrg(): boolean {
23
+ try { return localStorage.getItem(ORG_JOINED_KEY) === '1'; } catch { return false; }
24
+ }
25
+
26
+ function markOrgJoined(): void {
27
+ try { localStorage.setItem(ORG_JOINED_KEY, '1'); } catch { /* ignore */ }
28
+ }
29
 
30
  export default function WelcomeScreen() {
31
  const { createSession } = useSessionStore();
32
  const { setPlan, clearPanel, user } = useAgentStore();
33
  const [isCreating, setIsCreating] = useState(false);
34
  const [error, setError] = useState<string | null>(null);
35
+ const [orgJoined, setOrgJoined] = useState(hasJoinedOrg);
36
+ const joinLinkOpened = useRef(false);
37
 
38
  const inIframe = isInIframe();
39
  const isAuthenticated = user?.authenticated;
40
  const isDevUser = user?.username === 'dev';
41
 
42
+ // Auto-advance when user returns from the join link
43
+ useEffect(() => {
44
+ const handleVisibility = () => {
45
+ if (document.visibilityState !== 'visible' || !joinLinkOpened.current) return;
46
+ joinLinkOpened.current = false;
47
+ markOrgJoined();
48
+ setOrgJoined(true);
49
+ };
50
+
51
+ document.addEventListener('visibilitychange', handleVisibility);
52
+ return () => document.removeEventListener('visibilitychange', handleVisibility);
53
+ }, []);
54
+
55
  const tryCreateSession = useCallback(async () => {
56
  setIsCreating(true);
57
  setError(null);
 
119
  },
120
  };
121
 
122
+ // Description block (reused across screens)
123
+ const description = (
124
+ <Typography
125
+ variant="body1"
126
+ sx={{
127
+ color: 'var(--muted-text)',
128
+ maxWidth: 520,
129
+ mb: 5,
130
+ lineHeight: 1.8,
131
+ fontSize: '0.95rem',
132
+ textAlign: 'center',
133
+ px: 2,
134
+ '& strong': { color: 'var(--text)', fontWeight: 600 },
135
+ }}
136
+ >
137
+ A general-purpose AI agent for <strong>machine learning engineering</strong>.
138
+ It browses <strong>Hugging Face documentation</strong>, manages{' '}
139
+ <strong>repositories</strong>, launches <strong>training jobs</strong>,
140
+ and explores <strong>datasets</strong> β€” all through natural conversation.
141
+ </Typography>
142
+ );
143
+
144
+ // Which screen to show
145
+ const needsJoin = inIframe && !orgJoined;
146
+ const showOpenAgent = inIframe && orgJoined;
147
+ const showSignin = !inIframe && !isAuthenticated && !isDevUser;
148
+ const showReady = !inIframe && (isAuthenticated || isDevUser);
149
+
150
  return (
151
  <Box
152
  sx={{
 
182
  HF Agent
183
  </Typography>
184
 
185
+ {/* ── Iframe: join org (first visit only) ──────────────────── */}
186
+ {needsJoin && (
187
  <>
188
  <Typography
189
  variant="body1"
 
208
  href={ORG_JOIN_URL}
209
  target="_blank"
210
  rel="noopener noreferrer"
211
+ onClick={() => { joinLinkOpened.current = true; }}
212
  startIcon={<GroupAddIcon />}
213
  sx={primaryBtnSx}
214
  >
215
  Join ML Agent Explorers
216
  </Button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
217
  </>
218
  )}
219
 
220
+ {/* ── Iframe: already joined β†’ open Space ──────────────────── */}
221
+ {showOpenAgent && (
222
  <>
223
+ {description}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
  <Button
225
  variant="contained"
226
  size="large"
 
237
  )}
238
 
239
  {/* ── Direct: not logged in β†’ sign in ──────────────────────── */}
240
+ {showSignin && (
241
  <>
242
+ {description}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  <Button
244
  variant="contained"
245
  size="large"
 
266
  )}
267
 
268
  {/* ── Direct: authenticated β†’ start session ────────────────── */}
269
+ {showReady && (
270
  <>
271
+ {description}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
272
  <Button
273
  variant="contained"
274
  size="large"