fix(ui): first-login dashboard entrance restored + working Replay Intro

- playDashboardLoadOomph gated itself silent on the one entry that
  should be loud: onboarding is already flagged complete by the time the
  post-wizard dashboard mounts. force flag restores the full oomph there
  while keeping ordinary re-logins quiet (the intentional limit).
- OnboardingDone now hands Login a one-shot finale flag, so the login
  right after the wizard gets the full zoom + oomph even as a regular
  password login — which is exactly the demo flow (and TOTP logins).
- 'Replay intro' on the login screen actually replays: App.vue was
  instantly re-marking the intro as seen on onboarded nodes; an explicit
  one-shot replay flag now overrides every suppression rule (unit
  tested).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-07-15 10:48:39 +01:00
co-authored by Claude Fable 5
parent 994795e4d2
commit 4983ba4e20
7 changed files with 55 additions and 4 deletions
+3 -1
View File
@@ -369,7 +369,9 @@ onMounted(() => {
if (loginTransition.justCompletedOnboarding) {
// Full glitchy reveal — only on the very first dashboard entry
// right after onboarding (one-time event, persists in feel).
playDashboardLoadOomph()
// force=true: onboarding is already marked complete by now, so the
// un-forced call would gate itself silent.
playDashboardLoadOomph(true)
showZoomIn.value = true
loginTransition.setPendingWelcomeTyping(true)
loginTransition.setJustCompletedOnboarding(false)
+19
View File
@@ -477,6 +477,7 @@ async function handleLogin() {
stopSynthwave()
whooshAway.value = true
playLoginSuccessWhoosh()
consumeOnboardingFinale()
loginTransition.setJustLoggedIn(true)
await new Promise(r => setTimeout(r, 520))
await router.replace(loginRedirectTo.value).catch(() => {
@@ -512,6 +513,7 @@ async function handleTotpVerify() {
stopSynthwave()
whooshAway.value = true
playLoginSuccessWhoosh()
consumeOnboardingFinale()
loginTransition.setJustLoggedIn(true)
await new Promise(r => setTimeout(r, 520))
await router.replace(loginRedirectTo.value).catch(() => {
@@ -533,11 +535,28 @@ async function handleTotpVerify() {
}
}
/** A login right after the onboarding wizard (flag set by OnboardingDone)
* gets the FULL dashboard entrance — zoom + oomph — even though it's a
* regular password login (e.g. the demo). Subsequent logins stay
* deliberately low-key (justLoggedIn only). */
function consumeOnboardingFinale() {
try {
if (sessionStorage.getItem('archy_onboarding_finale') === '1') {
sessionStorage.removeItem('archy_onboarding_finale')
loginTransition.setJustCompletedOnboarding(true)
}
} catch { /* ignore */ }
}
function replayIntro() {
// Clear the intro seen flag
localStorage.removeItem('neode_intro_seen')
// Demo: also clear the per-day gate so the intro plays again now.
if (IS_DEMO) clearDemoIntroSeen()
// On an onboarded node App.vue instantly re-marks the intro as seen (that's
// what keeps fresh browsers on already-onboarded nodes from replaying it) —
// this explicit one-shot flag tells it the replay is deliberate.
try { sessionStorage.setItem('archipelago_replay_intro', '1') } catch { /* ignore */ }
// Navigate to root to trigger splash screen
window.location.href = '/'
}
+4
View File
@@ -120,6 +120,10 @@ onUnmounted(() => {
function goToLogin() {
playNavSound('action')
// The login that follows the wizard gets the full dashboard entrance
// (zoom + oomph) even when it's a regular password login (e.g. the demo)
// Login.vue consumes this flag on success.
try { sessionStorage.setItem('archy_onboarding_finale', '1') } catch { /* ignore */ }
router.push('/login').catch(() => {})
}
</script>