feat(onboarding): first-login wizard for incremental YouTube consent
After the clean name/email sign-in, a wizard walks the user through granting YouTube read (then optionally write) one step at a time, each with a plain rationale and an up-front heads-up about Google's "unverified app" screen. The visible step is derived from the granted scopes (can_read/can_write) so the flow resumes correctly across the full-page consent redirect; it's dismissible and reopenable from Settings -> Account, which now lists read and write as separate, individually-grantable access rows.
This commit is contained in:
parent
580d7f0e0d
commit
5215765b51
5 changed files with 302 additions and 29 deletions
33
frontend/src/lib/onboarding.ts
Normal file
33
frontend/src/lib/onboarding.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Onboarding wizard visibility, kept stable across the OAuth redirect round-trip.
|
||||
//
|
||||
// Granting a YouTube scope navigates away to Google's consent screen and back, which
|
||||
// fully reloads the SPA — so we can't hold the wizard's progress in React state. Instead
|
||||
// we derive the current step from the granted scopes (me.can_read / me.can_write) and use
|
||||
// two storage flags to decide whether to auto-open:
|
||||
//
|
||||
// ONBOARD_ACTIVE (sessionStorage) — set while the user is mid-flow (e.g. just clicked
|
||||
// "Connect"); makes the wizard reopen after the
|
||||
// redirect so they land on the next step.
|
||||
// ONBOARD_DISMISSED (localStorage) — set when the user skips the essential read step;
|
||||
// suppresses the auto-popup on future logins (they
|
||||
// can still reopen it from Settings → Account).
|
||||
|
||||
export const ONBOARD_ACTIVE = "subfeed.onboarding.active";
|
||||
export const ONBOARD_DISMISSED = "subfeed.onboarding.dismissed";
|
||||
|
||||
export function shouldAutoOpenOnboarding(me: { can_read: boolean }): boolean {
|
||||
if (sessionStorage.getItem(ONBOARD_ACTIVE)) return true;
|
||||
return !me.can_read && !localStorage.getItem(ONBOARD_DISMISSED);
|
||||
}
|
||||
|
||||
/** Mark a grant as in progress, then send the user to Google's consent screen. */
|
||||
export function beginGrant(access: "read" | "write"): void {
|
||||
sessionStorage.setItem(ONBOARD_ACTIVE, "1");
|
||||
window.location.href = `/auth/upgrade?access=${access}`;
|
||||
}
|
||||
|
||||
/** Leave the wizard. `dismiss` suppresses the future auto-popup (used when read is skipped). */
|
||||
export function endOnboarding(dismiss: boolean): void {
|
||||
sessionStorage.removeItem(ONBOARD_ACTIVE);
|
||||
if (dismiss) localStorage.setItem(ONBOARD_DISMISSED, "1");
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue