~james/core

core/web/src/lib/auth/onboarding.ts -rw-r--r-- 2.0 KiB
452f17b7 — james chore(import): snapshot james.dad.town/core at f70c71c7696a 15 hours ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import { browser } from "$app/env";
import { showsOnboardingNudge, type OnboardingState } from "#lib/api/preferences.ts";

const KEY_PREFIX = "tangled.onboarding.";

interface Onboarding {
	done: string | null;
	profile: string | null;
}

const keyOf = (did: string) => `${KEY_PREFIX}${did}`;

const read = (did: string): Onboarding => {
	const empty: Onboarding = { done: null, profile: null };
	if (!browser) return empty;
	try {
		const raw = localStorage.getItem(keyOf(did));
		if (!raw) return empty;
		const parsed: unknown = JSON.parse(raw);
		// legacy storage stored done timestamp directly as string
		if (typeof parsed === "string") return { ...empty, done: parsed };
		const value = parsed as Partial<Onboarding> | null;
		return {
			done: typeof value?.done === "string" ? value.done : null,
			profile: typeof value?.profile === "string" ? value.profile : null
		};
	} catch {
		return empty;
	}
};

const write = (did: string, patch: Partial<Onboarding>): void => {
	if (!browser) return;
	try {
		localStorage.setItem(keyOf(did), JSON.stringify({ ...read(did), ...patch }));
	} catch {
		// storage access can fail in private browsing; flow is idempotent
	}
};

export const onboardingDone = (did: string): boolean => read(did).done !== null;

export const markOnboardingDone = (did: string): void => {
	write(did, { done: new Date().toISOString() });
};

export const profileImported = (did: string): boolean => read(did).profile !== null;

export const markProfileImported = (did: string): void => {
	write(did, { profile: new Date().toISOString() });
};

export const NUDGE_COOKIE = "tangled.onboardingNudge";

export const rememberNudge = (did: string | null, state: OnboardingState | null): void => {
	if (!browser || !did) return;
	const secure = location.protocol === "https:" ? "; secure" : "";
	document.cookie = showsOnboardingNudge(state)
		? `${NUDGE_COOKIE}=${encodeURIComponent(did)}; path=/; max-age=31536000; samesite=lax${secure}`
		: `${NUDGE_COOKIE}=; path=/; max-age=0; samesite=lax`;
};