commit
2eaf4ad75b
@ -113,6 +113,11 @@ export const useChatSocket = (
|
||||
emit("fetch_balance", { chatId });
|
||||
}, [emit, chatId]);
|
||||
|
||||
// Auto top-up: silent flow (no UI prompt)
|
||||
const autoTopUpInProgressRef = useRef(false);
|
||||
// Timer for delayed unlock after error
|
||||
const autoTopUpUnlockTimerRef = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
// Auto top-up: use existing single checkout flow
|
||||
const { handleSingleCheckout, isLoading: isAutoTopUpLoading } =
|
||||
useSingleCheckout({
|
||||
@ -120,15 +125,18 @@ export const useChatSocket = (
|
||||
onError: () => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error("Auto top-up payment failed");
|
||||
// Release in-flight lock on error so a future event can retry
|
||||
// Throttle retries: keep the lock for 30 seconds after an error
|
||||
if (autoTopUpUnlockTimerRef.current) {
|
||||
clearTimeout(autoTopUpUnlockTimerRef.current);
|
||||
}
|
||||
autoTopUpUnlockTimerRef.current = setTimeout(() => {
|
||||
autoTopUpInProgressRef.current = false;
|
||||
autoTopUpUnlockTimerRef.current = null;
|
||||
}, 30_000);
|
||||
},
|
||||
returnUrl: typeof window !== "undefined" ? window.location.href : "",
|
||||
});
|
||||
|
||||
// Auto top-up: silent flow (no UI prompt)
|
||||
const autoTopUpInProgressRef = useRef(false);
|
||||
|
||||
const balancePollId = useRef<NodeJS.Timeout | null>(null);
|
||||
// Avoid immediate leave_chat right after join in React 18 StrictMode (dev) double-invoke
|
||||
// We debounce leave so that a quick remount cancels it, but real navigation (or chat switch) proceeds.
|
||||
@ -203,12 +211,20 @@ export const useChatSocket = (
|
||||
// If auto top-up was in-flight, release the lock only after balance became positive
|
||||
if (autoTopUpInProgressRef.current && b?.data?.balance > 0) {
|
||||
autoTopUpInProgressRef.current = false;
|
||||
if (autoTopUpUnlockTimerRef.current) {
|
||||
clearTimeout(autoTopUpUnlockTimerRef.current);
|
||||
autoTopUpUnlockTimerRef.current = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
useSocketEvent("balance_updated", b => {
|
||||
setBalance(prev => (prev ? { ...prev, balance: b.data.balance } : null));
|
||||
if (autoTopUpInProgressRef.current && b?.data?.balance > 0) {
|
||||
autoTopUpInProgressRef.current = false;
|
||||
if (autoTopUpUnlockTimerRef.current) {
|
||||
clearTimeout(autoTopUpUnlockTimerRef.current);
|
||||
autoTopUpUnlockTimerRef.current = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
useSocketEvent("session_started", s => setSession(s.data));
|
||||
@ -310,6 +326,16 @@ export const useChatSocket = (
|
||||
};
|
||||
}, [session, endSession]);
|
||||
|
||||
// Cleanup pending unlock timer on unmount
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (autoTopUpUnlockTimerRef.current) {
|
||||
clearTimeout(autoTopUpUnlockTimerRef.current);
|
||||
autoTopUpUnlockTimerRef.current = null;
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
const isAvailableChatting =
|
||||
!!balance?.balance && !!session && !isSessionExpired;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user