feat(chat): render role-bound payment guidance
Docker Image / Build and Push Docker Image (push) Successful in 5m2s
Docker Image / Build and Push Docker Image (push) Successful in 5m2s
This commit is contained in:
@@ -20,6 +20,7 @@ import {
|
||||
import type { ChatPromotionState } from "@/stores/chat/helper/promotion";
|
||||
import type { ChatUnlockPaywallRequest } from "@/stores/chat/chat-state";
|
||||
import type { UiMessage } from "@/stores/chat/ui-message";
|
||||
import { recordChatActionEventById } from "@/lib/chat/chat_action_events";
|
||||
import { useUserSelector } from "@/stores/user/user-context";
|
||||
|
||||
import { getInsufficientCreditsSubscriptionType } from "../chat-screen.helpers";
|
||||
@@ -48,6 +49,7 @@ export interface ChatUnlockDialogModel {
|
||||
lockedCount: number;
|
||||
isLoading: boolean;
|
||||
errorMessage: string | null;
|
||||
guidance: import("@/data/schemas/chat").PaymentGuidance | null;
|
||||
};
|
||||
closeHistoryUnlock: () => void;
|
||||
confirmHistoryUnlock: () => void;
|
||||
@@ -87,6 +89,8 @@ export function useChatUnlockCoordinator({
|
||||
isUnlockingHistory: state.matches({ userSession: "unlockingHistory" }),
|
||||
lockedHistoryCount: state.context.lockedHistoryCount,
|
||||
unlockHistoryError: state.context.unlockHistoryError,
|
||||
unlockHistoryPaymentGuidance:
|
||||
state.context.unlockHistoryPaymentGuidance,
|
||||
unlockHistoryPromptVisible: state.context.unlockHistoryPromptVisible,
|
||||
unlockPaywallRequest: state.context.unlockPaywallRequest,
|
||||
}),
|
||||
@@ -97,6 +101,20 @@ export function useChatUnlockCoordinator({
|
||||
? chatState.unlockPaywallRequest
|
||||
: null;
|
||||
|
||||
useEffect(() => {
|
||||
const guidance = chatState.unlockHistoryPaymentGuidance;
|
||||
if (!enabled || guidance?.characterId !== chatState.characterId) return;
|
||||
void recordChatActionEventById(
|
||||
guidance.guidanceId,
|
||||
chatState.characterId,
|
||||
"viewed",
|
||||
).catch(() => undefined);
|
||||
}, [
|
||||
chatState.characterId,
|
||||
chatState.unlockHistoryPaymentGuidance,
|
||||
enabled,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!unlockPaywallRequest) {
|
||||
trackedPaywallRef.current = null;
|
||||
@@ -120,7 +138,15 @@ export function useChatUnlockCoordinator({
|
||||
},
|
||||
{ isVip },
|
||||
);
|
||||
}, [isVip, unlockPaywallRequest]);
|
||||
const guidance = unlockPaywallRequest.paymentGuidance;
|
||||
if (guidance?.characterId === chatState.characterId) {
|
||||
void recordChatActionEventById(
|
||||
guidance.guidanceId,
|
||||
chatState.characterId,
|
||||
"viewed",
|
||||
).catch(() => undefined);
|
||||
}
|
||||
}, [chatState.characterId, isVip, unlockPaywallRequest]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!enabled) return;
|
||||
@@ -212,6 +238,32 @@ export function useChatUnlockCoordinator({
|
||||
}
|
||||
|
||||
function confirmHistoryUnlock(): void {
|
||||
const guidance =
|
||||
chatState.unlockHistoryPaymentGuidance?.characterId ===
|
||||
chatState.characterId
|
||||
? chatState.unlockHistoryPaymentGuidance
|
||||
: null;
|
||||
if (guidance) {
|
||||
if (guidance.mode !== "guide") return;
|
||||
void recordChatActionEventById(
|
||||
guidance.guidanceId,
|
||||
chatState.characterId,
|
||||
"opened",
|
||||
).catch(() => undefined);
|
||||
navigator.openSubscription({
|
||||
type:
|
||||
isVip || !guidance.purchaseOptions.includes("vip")
|
||||
? "topup"
|
||||
: "vip",
|
||||
returnTo: "chat",
|
||||
chatActionId: guidance.guidanceId,
|
||||
analytics: {
|
||||
entryPoint: "chat_unlock",
|
||||
triggerReason: "insufficient_credits",
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
chatDispatch({ type: "ChatUnlockHistoryConfirmed" });
|
||||
}
|
||||
|
||||
@@ -221,6 +273,12 @@ export function useChatUnlockCoordinator({
|
||||
|
||||
function confirmPaywall(): void {
|
||||
if (!unlockPaywallRequest) return;
|
||||
const guidance =
|
||||
unlockPaywallRequest.paymentGuidance?.characterId ===
|
||||
chatState.characterId
|
||||
? unlockPaywallRequest.paymentGuidance
|
||||
: null;
|
||||
if (guidance && guidance.mode !== "guide") return;
|
||||
|
||||
const returnUrl = resolveChatUnlockReturnUrl(
|
||||
unlockPaywallRequest,
|
||||
@@ -231,6 +289,13 @@ export function useChatUnlockCoordinator({
|
||||
},
|
||||
);
|
||||
chatDispatch({ type: "ChatUnlockPaywallNavigationConsumed" });
|
||||
if (guidance) {
|
||||
void recordChatActionEventById(
|
||||
guidance.guidanceId,
|
||||
chatState.characterId,
|
||||
"opened",
|
||||
).catch(() => undefined);
|
||||
}
|
||||
navigator.openSubscriptionForPendingUnlock({
|
||||
displayMessageId: unlockPaywallRequest.displayMessageId,
|
||||
messageId: unlockPaywallRequest.messageId,
|
||||
@@ -239,13 +304,17 @@ export function useChatUnlockCoordinator({
|
||||
clientLockId: unlockPaywallRequest.clientLockId,
|
||||
promotion: unlockPaywallRequest.promotion,
|
||||
returnUrl,
|
||||
type: getInsufficientCreditsSubscriptionType(isVip),
|
||||
type:
|
||||
isVip || (guidance && !guidance.purchaseOptions.includes("vip"))
|
||||
? "topup"
|
||||
: getInsufficientCreditsSubscriptionType(isVip),
|
||||
analytics: {
|
||||
entryPoint: "chat_unlock",
|
||||
triggerReason: unlockPaywallRequest.promotion
|
||||
? "ad_landing"
|
||||
: "insufficient_credits",
|
||||
},
|
||||
...(guidance ? { chatActionId: guidance.guidanceId } : {}),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -258,6 +327,7 @@ export function useChatUnlockCoordinator({
|
||||
lockedCount: chatState.lockedHistoryCount,
|
||||
isLoading: chatState.isUnlockingHistory,
|
||||
errorMessage: chatState.unlockHistoryError,
|
||||
guidance: chatState.unlockHistoryPaymentGuidance,
|
||||
},
|
||||
closeHistoryUnlock,
|
||||
confirmHistoryUnlock,
|
||||
|
||||
Reference in New Issue
Block a user