feat(FN-1862): add completion state tracking for onboarding

- Add markOnboardingCompleted() to set completedAt timestamp when user finishes onboarding
- Add isOnboardingCompleted() to check if onboarding was completed (vs dismissed)
- Update ModelOnboardingModal to call markOnboardingCompleted on successful completion
- Skip onboarding auto-open when already completed locally
- Add completion state tracking tests in ModelOnboardingModal.test.tsx
- Add model-onboarding-state unit tests
- Update useAuthOnboarding to check local completion state before auto-opening
- Document localStorage completion state tracking pattern in .fusion/memory.md
This commit is contained in:
Fusion
2026-04-14 23:44:40 -07:00
committed by gsxdsm
parent 6d685a542b
commit a51e75941c
49 changed files with 572 additions and 196 deletions

View File

@@ -26,9 +26,6 @@ type AppListenerHandle = { remove: () => Promise<void> };
type HashChangeEventHandler = (event: HashChangeEvent) => void;
/** Fallback listener type for untyped event handling */
type FallbackListener = (...args: unknown[]) => void;
export class DeepLinkManager extends EventEmitter {
private readonly scheme: string;
private readonly universalLinkHosts: string[];
@@ -47,8 +44,8 @@ export class DeepLinkManager extends EventEmitter {
event: K,
listener: (payload: DeepLinkEventMap[K]) => void,
): this;
override on(event: string | symbol, listener: FallbackListener): this;
override on(event: string | symbol, listener: FallbackListener): this {
override on(event: string | symbol, listener: (...args: any[]) => void): this;
override on(event: string | symbol, listener: (...args: any[]) => void): this {
return super.on(event, listener);
}
@@ -56,8 +53,8 @@ export class DeepLinkManager extends EventEmitter {
event: K,
listener: (payload: DeepLinkEventMap[K]) => void,
): this;
override off(event: string | symbol, listener: FallbackListener): this;
override off(event: string | symbol, listener: FallbackListener): this {
override off(event: string | symbol, listener: (...args: any[]) => void): this;
override off(event: string | symbol, listener: (...args: any[]) => void): this {
return super.off(event, listener);
}

View File

@@ -34,9 +34,6 @@ export interface PushNotificationManagerOptions {
type PushNotificationsModule = typeof import("@capacitor/push-notifications");
/** Fallback listener type for untyped event handling */
type FallbackListener = (...args: unknown[]) => void;
export class PushNotificationManager extends EventEmitter {
private deviceToken: string | undefined;
private ntfyBaseUrl: string;
@@ -59,8 +56,8 @@ export class PushNotificationManager extends EventEmitter {
eventName: K,
listener: (payload: PushNotificationEventMap[K]) => void,
): this;
override on(eventName: string | symbol, listener: FallbackListener): this;
override on(eventName: string | symbol, listener: FallbackListener): this {
override on(eventName: string | symbol, listener: (...args: any[]) => void): this;
override on(eventName: string | symbol, listener: (...args: any[]) => void): this {
return super.on(eventName, listener);
}
@@ -68,8 +65,8 @@ export class PushNotificationManager extends EventEmitter {
eventName: K,
listener: (payload: PushNotificationEventMap[K]) => void,
): this;
override off(eventName: string | symbol, listener: FallbackListener): this;
override off(eventName: string | symbol, listener: FallbackListener): this {
override off(eventName: string | symbol, listener: (...args: any[]) => void): this;
override off(eventName: string | symbol, listener: (...args: any[]) => void): this {
return super.off(eventName, listener);
}

View File

@@ -29,9 +29,6 @@ type ShareCapacitorResult = {
activityType?: string;
};
/** Fallback listener type for untyped event handling */
type FallbackListener = (...args: unknown[]) => void;
export class ShareManager extends EventEmitter {
private readonly deepLinkBaseUrl: string;
private initialized = false;
@@ -46,8 +43,8 @@ export class ShareManager extends EventEmitter {
event: K,
listener: (payload: ShareEventMap[K]) => void,
): this;
override on(event: string | symbol, listener: FallbackListener): this;
override on(event: string | symbol, listener: FallbackListener): this {
override on(event: string | symbol, listener: (...args: any[]) => void): this;
override on(event: string | symbol, listener: (...args: any[]) => void): this {
return super.on(event, listener);
}
@@ -55,8 +52,8 @@ export class ShareManager extends EventEmitter {
event: K,
listener: (payload: ShareEventMap[K]) => void,
): this;
override off(event: string | symbol, listener: FallbackListener): this;
override off(event: string | symbol, listener: FallbackListener): this {
override off(event: string | symbol, listener: (...args: any[]) => void): this;
override off(event: string | symbol, listener: (...args: any[]) => void): this {
return super.off(event, listener);
}