124 lines
3.6 KiB
TypeScript
124 lines
3.6 KiB
TypeScript
"use client";
|
|
|
|
import { type Dispatch, useEffect, useRef } from "react";
|
|
|
|
import type { LoginStatus } from "@/data/schemas/auth";
|
|
import { useGuestLoginBootstrap } from "@/hooks/use-guest-login-bootstrap";
|
|
import { behaviorAnalytics } from "@/lib/analytics";
|
|
import { useActiveCharacterRoutes } from "@/providers/character-provider";
|
|
import { useAppNavigator } from "@/router/use-app-navigator";
|
|
import type { AuthEvent } from "@/stores/auth/auth-events";
|
|
import type { PrivateRoomEvent } from "@/stores/private-room";
|
|
import type { PrivateRoomUnlockPaywallRequest } from "@/stores/private-room/private-room-state";
|
|
import { useUserDispatch } from "@/stores/user/user-context";
|
|
|
|
export interface UsePrivateRoomBootstrapFlowInput {
|
|
authDispatch: Dispatch<AuthEvent>;
|
|
hasInitialized: boolean;
|
|
isAuthLoading: boolean;
|
|
loginStatus: LoginStatus;
|
|
roomDispatch: Dispatch<PrivateRoomEvent>;
|
|
roomStatus: string;
|
|
}
|
|
|
|
export interface UsePrivateRoomUnlockPaywallNavigationInput {
|
|
loginStatus: LoginStatus;
|
|
roomDispatch: Dispatch<PrivateRoomEvent>;
|
|
unlockPaywallRequest: PrivateRoomUnlockPaywallRequest | null;
|
|
}
|
|
|
|
export function isPrivateRoomAuthRequired(loginStatus: LoginStatus): boolean {
|
|
return loginStatus === "guest" || loginStatus === "notLoggedIn";
|
|
}
|
|
|
|
export function usePrivateRoomBootstrapFlow({
|
|
authDispatch,
|
|
hasInitialized,
|
|
isAuthLoading,
|
|
loginStatus,
|
|
roomDispatch,
|
|
roomStatus,
|
|
}: UsePrivateRoomBootstrapFlowInput): void {
|
|
const previousLoginStatusRef = useRef(loginStatus);
|
|
|
|
useGuestLoginBootstrap({
|
|
dispatch: authDispatch,
|
|
hasInitialized,
|
|
isLoading: isAuthLoading,
|
|
loginStatus,
|
|
});
|
|
|
|
useEffect(() => {
|
|
if (!hasInitialized || isAuthLoading) return;
|
|
if (loginStatus === "notLoggedIn") return;
|
|
|
|
const previousLoginStatus = previousLoginStatusRef.current;
|
|
previousLoginStatusRef.current = loginStatus;
|
|
|
|
if (roomStatus === "idle") {
|
|
roomDispatch({ type: "PrivateRoomInit" });
|
|
return;
|
|
}
|
|
|
|
if (previousLoginStatus !== loginStatus && roomStatus !== "loading") {
|
|
roomDispatch({ type: "PrivateRoomRefresh" });
|
|
}
|
|
}, [
|
|
hasInitialized,
|
|
isAuthLoading,
|
|
loginStatus,
|
|
roomDispatch,
|
|
roomStatus,
|
|
]);
|
|
}
|
|
|
|
export function usePrivateRoomUnlockPaywallNavigation({
|
|
loginStatus,
|
|
roomDispatch,
|
|
unlockPaywallRequest,
|
|
}: UsePrivateRoomUnlockPaywallNavigationInput): void {
|
|
const navigator = useAppNavigator();
|
|
const characterRoutes = useActiveCharacterRoutes();
|
|
|
|
useEffect(() => {
|
|
if (!unlockPaywallRequest) return;
|
|
|
|
if (isPrivateRoomAuthRequired(loginStatus)) {
|
|
navigator.openAuth(characterRoutes.privateRoom);
|
|
} else {
|
|
behaviorAnalytics.paywallShown({
|
|
entryPoint: "private_album_unlock",
|
|
triggerReason: "insufficient_credits",
|
|
});
|
|
navigator.openSubscription({
|
|
type: "topup",
|
|
returnTo: "private-room",
|
|
analytics: {
|
|
entryPoint: "private_album_unlock",
|
|
triggerReason: "insufficient_credits",
|
|
},
|
|
});
|
|
}
|
|
roomDispatch({ type: "PrivateRoomUnlockPaywallConsumed" });
|
|
}, [
|
|
characterRoutes.privateRoom,
|
|
loginStatus,
|
|
navigator,
|
|
roomDispatch,
|
|
unlockPaywallRequest,
|
|
]);
|
|
}
|
|
|
|
export function usePrivateRoomUnlockSuccessRefresh(
|
|
unlockSuccessNonce: number,
|
|
): void {
|
|
const userDispatch = useUserDispatch();
|
|
const lastUnlockSuccessNonceRef = useRef(0);
|
|
|
|
useEffect(() => {
|
|
if (unlockSuccessNonce <= lastUnlockSuccessNonceRef.current) return;
|
|
lastUnlockSuccessNonceRef.current = unlockSuccessNonce;
|
|
userDispatch({ type: "UserFetch" });
|
|
}, [unlockSuccessNonce, userDispatch]);
|
|
}
|