mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 17:43:47 +00:00
fix: prevent popup cascade when Telegram callback doesn't fire
- Add persistent popupClosed listener that resets state even after per-call listener is removed by timeout - Increase safety timeout from 5s to 30s to give user time to interact - On WebAppPopupOpened error, keep popupOpen=true to block retries instead of resetting and allowing infinite error loop - Remove callback param from showPopup to avoid dual-listener conflicts - Remove debug console logs
This commit is contained in:
@@ -184,6 +184,17 @@ function createDialogController(): DialogController {
|
||||
const inTelegram = isInTelegramWebApp();
|
||||
let popupOpen = false;
|
||||
|
||||
// Persistent listener: resets popupOpen whenever Telegram reports popup closed,
|
||||
// even if our per-call listener was already removed.
|
||||
if (inTelegram) {
|
||||
const tg = getTelegram();
|
||||
if (tg?.onEvent) {
|
||||
tg.onEvent('popupClosed', (() => {
|
||||
popupOpen = false;
|
||||
}) as (...args: unknown[]) => void);
|
||||
}
|
||||
}
|
||||
|
||||
function showPopupSafe<T>(
|
||||
params: Parameters<NonNullable<TelegramWebApp['showPopup']>>[0],
|
||||
mapResult: (buttonId: string) => T,
|
||||
@@ -203,8 +214,6 @@ function createDialogController(): DialogController {
|
||||
popupOpen = true;
|
||||
let settled = false;
|
||||
|
||||
console.log('[popup] opening', JSON.stringify(params));
|
||||
|
||||
const cleanup = () => {
|
||||
if (settled) return;
|
||||
settled = true;
|
||||
@@ -214,7 +223,6 @@ function createDialogController(): DialogController {
|
||||
};
|
||||
|
||||
const onPopupClosed = ((...args: unknown[]) => {
|
||||
console.log('[popup] popupClosed event', JSON.stringify(args));
|
||||
if (settled) return;
|
||||
const event = args[0] as { button_id?: string } | undefined;
|
||||
const buttonId = event?.button_id ?? '';
|
||||
@@ -223,24 +231,29 @@ function createDialogController(): DialogController {
|
||||
}) as (...args: unknown[]) => void;
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
console.log('[popup] timeout — force reset');
|
||||
if (settled) return;
|
||||
cleanup();
|
||||
resolve(mapResult(''));
|
||||
}, 5_000);
|
||||
}, 30_000);
|
||||
|
||||
tg.onEvent?.('popupClosed', onPopupClosed);
|
||||
|
||||
try {
|
||||
tg.showPopup(params, (buttonId) => {
|
||||
console.log('[popup] callback fired, buttonId=', buttonId);
|
||||
if (settled) return;
|
||||
cleanup();
|
||||
resolve(mapResult(buttonId));
|
||||
});
|
||||
console.log('[popup] showPopup called OK');
|
||||
tg.showPopup(params);
|
||||
} catch (e) {
|
||||
console.error('[popup] showPopup threw', e);
|
||||
// Telegram SDK says a popup is already open — don't reset popupOpen,
|
||||
// so subsequent calls are silently blocked until the popup actually closes.
|
||||
const isAlreadyOpen = e instanceof Error && e.message?.includes('WebAppPopupOpened');
|
||||
|
||||
if (isAlreadyOpen) {
|
||||
settled = true;
|
||||
clearTimeout(timer);
|
||||
tg.offEvent?.('popupClosed', onPopupClosed);
|
||||
// popupOpen stays true — the persistent listener will reset it
|
||||
resolve(mapResult(''));
|
||||
return;
|
||||
}
|
||||
|
||||
cleanup();
|
||||
resolve(fallback());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user