150 lines
4.3 KiB
TypeScript
150 lines
4.3 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 {
|
|
useActiveCharacter,
|
|
useActiveCharacterRoutes,
|
|
} from "@/providers/character-provider";
|
|
import { useAppNavigator } from "@/router/use-app-navigator";
|
|
import type { AuthEvent } from "@/stores/auth/auth-events";
|
|
import type { PrivateZoneEvent } from "@/stores/private-zone";
|
|
import type { PrivateZoneUnlockPaywallRequest } from "@/stores/private-zone/private-zone-state";
|
|
import { useUserDispatch } from "@/stores/user/user-context";
|
|
import { recordChatActionEventById } from "@/lib/chat/chat_action_events";
|
|
|
|
export interface UsePrivateZoneBootstrapFlowInput {
|
|
authDispatch: Dispatch<AuthEvent>;
|
|
hasInitialized: boolean;
|
|
isAuthLoading: boolean;
|
|
loginStatus: LoginStatus;
|
|
roomDispatch: Dispatch<PrivateZoneEvent>;
|
|
roomStatus: string;
|
|
}
|
|
|
|
export interface UsePrivateZoneUnlockPaywallNavigationInput {
|
|
loginStatus: LoginStatus;
|
|
roomDispatch: Dispatch<PrivateZoneEvent>;
|
|
unlockPaywallRequest: PrivateZoneUnlockPaywallRequest | null;
|
|
isVip: boolean;
|
|
}
|
|
|
|
export function isPrivateZoneAuthRequired(loginStatus: LoginStatus): boolean {
|
|
return loginStatus === "guest" || loginStatus === "notLoggedIn";
|
|
}
|
|
|
|
export function usePrivateZoneBootstrapFlow({
|
|
authDispatch,
|
|
hasInitialized,
|
|
isAuthLoading,
|
|
loginStatus,
|
|
roomDispatch,
|
|
roomStatus,
|
|
}: UsePrivateZoneBootstrapFlowInput): 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: "PrivateZoneInit" });
|
|
return;
|
|
}
|
|
|
|
if (previousLoginStatus !== loginStatus && roomStatus !== "loading") {
|
|
roomDispatch({ type: "PrivateZoneRefresh" });
|
|
}
|
|
}, [
|
|
hasInitialized,
|
|
isAuthLoading,
|
|
loginStatus,
|
|
roomDispatch,
|
|
roomStatus,
|
|
]);
|
|
}
|
|
|
|
export function usePrivateZoneUnlockPaywallNavigation({
|
|
loginStatus,
|
|
roomDispatch,
|
|
unlockPaywallRequest,
|
|
isVip,
|
|
}: UsePrivateZoneUnlockPaywallNavigationInput): void {
|
|
const navigator = useAppNavigator();
|
|
const character = useActiveCharacter();
|
|
const characterRoutes = useActiveCharacterRoutes();
|
|
|
|
useEffect(() => {
|
|
if (!unlockPaywallRequest) return;
|
|
|
|
if (isPrivateZoneAuthRequired(loginStatus)) {
|
|
navigator.openAuth(characterRoutes.privateZone);
|
|
} else {
|
|
behaviorAnalytics.paywallShown({
|
|
entryPoint: "private_album_unlock",
|
|
triggerReason: "insufficient_credits",
|
|
});
|
|
const guidance = unlockPaywallRequest.paymentGuidance;
|
|
const activeGuidance =
|
|
guidance?.characterId === character.id ? guidance : null;
|
|
if (activeGuidance) {
|
|
void recordChatActionEventById(
|
|
activeGuidance.guidanceId,
|
|
activeGuidance.characterId,
|
|
"opened",
|
|
).catch(() => undefined);
|
|
}
|
|
navigator.openSubscription({
|
|
type:
|
|
isVip ||
|
|
(activeGuidance && !activeGuidance.purchaseOptions.includes("vip"))
|
|
? "topup"
|
|
: "vip",
|
|
returnTo: "private-zone",
|
|
...(activeGuidance
|
|
? { chatActionId: activeGuidance.guidanceId }
|
|
: {}),
|
|
analytics: {
|
|
entryPoint: "private_album_unlock",
|
|
triggerReason: "insufficient_credits",
|
|
},
|
|
});
|
|
}
|
|
roomDispatch({ type: "PrivateZoneUnlockPaywallConsumed" });
|
|
}, [
|
|
characterRoutes.privateZone,
|
|
character.id,
|
|
loginStatus,
|
|
isVip,
|
|
navigator,
|
|
roomDispatch,
|
|
unlockPaywallRequest,
|
|
]);
|
|
}
|
|
|
|
export function usePrivateZoneUnlockSuccessRefresh(
|
|
unlockSuccessNonce: number,
|
|
): void {
|
|
const userDispatch = useUserDispatch();
|
|
const lastUnlockSuccessNonceRef = useRef(0);
|
|
|
|
useEffect(() => {
|
|
if (unlockSuccessNonce <= lastUnlockSuccessNonceRef.current) return;
|
|
lastUnlockSuccessNonceRef.current = unlockSuccessNonce;
|
|
userDispatch({ type: "UserFetch" });
|
|
}, [unlockSuccessNonce, userDispatch]);
|
|
}
|