fix(subscription): sync vip state before chat return
This commit is contained in:
@@ -68,8 +68,11 @@ export function SubscriptionScreen({
|
||||
const refreshedPaidOrderRef = useRef<string | null>(null);
|
||||
const resumedPendingOrderRef = useRef<string | null>(null);
|
||||
const successDialogShownOrderRef = useRef<string | null>(null);
|
||||
const syncedVipOrderRef = useRef<string | null>(null);
|
||||
const [showPaymentSuccessDialog, setShowPaymentSuccessDialog] =
|
||||
useState(false);
|
||||
const [pendingChatReturnAfterVipSync, setPendingChatReturnAfterVipSync] =
|
||||
useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (payment.status === "idle") {
|
||||
@@ -84,6 +87,35 @@ export function SubscriptionScreen({
|
||||
userDispatch({ type: "UserFetch" });
|
||||
}, [payment.currentOrderId, payment.isPaid, userDispatch]);
|
||||
|
||||
useEffect(() => {
|
||||
const currentUser = user.currentUser;
|
||||
const canMarkVipSynced =
|
||||
subscriptionType === "vip" &&
|
||||
payment.isPaid &&
|
||||
payment.currentOrderId &&
|
||||
payment.vipStatus?.isVip === true &&
|
||||
currentUser &&
|
||||
currentUser.isVip !== true;
|
||||
if (!canMarkVipSynced) return;
|
||||
if (syncedVipOrderRef.current === payment.currentOrderId) return;
|
||||
|
||||
syncedVipOrderRef.current = payment.currentOrderId;
|
||||
userDispatch({
|
||||
type: "UserUpdate",
|
||||
user: {
|
||||
...currentUser,
|
||||
isVip: true,
|
||||
},
|
||||
});
|
||||
}, [
|
||||
payment.currentOrderId,
|
||||
payment.isPaid,
|
||||
payment.vipStatus?.isVip,
|
||||
subscriptionType,
|
||||
user.currentUser,
|
||||
userDispatch,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!payment.isPaid || !payment.currentOrderId) return;
|
||||
if (successDialogShownOrderRef.current === payment.currentOrderId) return;
|
||||
@@ -181,7 +213,8 @@ export function SubscriptionScreen({
|
||||
? "Choose a voice package"
|
||||
: "Choose a subscription plan";
|
||||
|
||||
const handlePaymentSuccessClose = () => {
|
||||
const finishPaymentSuccessClose = () => {
|
||||
setPendingChatReturnAfterVipSync(false);
|
||||
setShowPaymentSuccessDialog(false);
|
||||
paymentDispatch({ type: "PaymentReset" });
|
||||
if (returnTo === "chat") {
|
||||
@@ -189,6 +222,45 @@ export function SubscriptionScreen({
|
||||
}
|
||||
};
|
||||
|
||||
const handlePaymentSuccessClose = () => {
|
||||
const shouldWaitForVipSync =
|
||||
returnTo === "chat" &&
|
||||
subscriptionType === "vip" &&
|
||||
user.currentUser?.isVip !== true;
|
||||
|
||||
if (shouldWaitForVipSync) {
|
||||
setPendingChatReturnAfterVipSync(true);
|
||||
if (payment.vipStatus?.isVip === true && user.currentUser) {
|
||||
userDispatch({
|
||||
type: "UserUpdate",
|
||||
user: {
|
||||
...user.currentUser,
|
||||
isVip: true,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
userDispatch({ type: "UserFetch" });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
finishPaymentSuccessClose();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!pendingChatReturnAfterVipSync) return;
|
||||
if (subscriptionType === "vip" && user.currentUser?.isVip !== true) return;
|
||||
|
||||
const timer = window.setTimeout(() => {
|
||||
finishPaymentSuccessClose();
|
||||
}, 0);
|
||||
|
||||
return () => window.clearTimeout(timer);
|
||||
// `finishPaymentSuccessClose` intentionally stays local to this component;
|
||||
// this effect is gated by pendingChatReturnAfterVipSync to avoid repeated closes.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [pendingChatReturnAfterVipSync, subscriptionType, user.currentUser?.isVip]);
|
||||
|
||||
useEffect(() => {
|
||||
if (payment.isLoadingPlans || payment.plans.length === 0) return;
|
||||
if (selectedPlan !== null) return;
|
||||
|
||||
Reference in New Issue
Block a user