Fix: debounce login + try/catch TG.showAlert

- emailLogin: защита от двойного клика (_loginInProgress)
- api(): timeout 20s + cache:'no-store' + redirect:'follow'
- tg.js: try/catch вокруг showAlert/showConfirm (WebAppMethodUnsupported fix)
This commit is contained in:
root 2026-08-20 21:52:52 +00:00
parent ae652e37f5
commit 36a81a05ec
3 changed files with 25 additions and 7 deletions

View File

@ -58,13 +58,19 @@ async function api(path, opts = {}, _retry = 0) {
o.body = JSON.stringify(o.body);
}
let r;
// timeout 15s — иначе UI висит вечно
// timeout 20s
const controller = new AbortController();
const tid = setTimeout(() => controller.abort(), 15000);
const tid = setTimeout(() => controller.abort(), 20000);
const t0 = Date.now();
try {
// credentials:'include' — браузер шлёт cookies (HttpOnly buhapp_at)
r = await fetch(API_BASE + path, { ...o, credentials: 'include', signal: controller.signal });
r = await fetch(API_BASE + path, {
...o,
credentials: 'include',
signal: controller.signal,
cache: 'no-store',
redirect: 'follow',
});
} catch (networkErr) {
clearTimeout(tid);
const ms = Date.now() - t0;

View File

@ -243,6 +243,8 @@ const App = {
},
async emailLogin() {
if (this._loginInProgress) return; // защита от двойного клика
this._loginInProgress = true;
const email = document.getElementById('el-email').value.trim();
const pass = document.getElementById('el-pass').value;
const btn = document.getElementById('el-login');
@ -260,6 +262,8 @@ const App = {
if (hint) { hint.textContent = '⚠️ ' + e.message; hint.style.color = 'var(--danger)'; }
TG_APP.showAlert('Ошибка входа: ' + e.message);
if (btn) { btn.disabled = false; btn.textContent = 'Войти'; }
} finally {
this._loginInProgress = false;
}
},

View File

@ -21,12 +21,20 @@ window.TG_APP = {
} catch (e) {}
},
showAlert: (msg) => {
if (TG?.showAlert) TG.showAlert(msg);
else alert(msg);
try {
if (TG?.showAlert) TG.showAlert(String(msg));
else alert(String(msg));
} catch (e) {
try { alert(String(msg)); } catch {}
}
},
showConfirm: (msg) => {
if (TG?.showConfirm) return new Promise((r) => TG.showConfirm(msg, r));
return Promise.resolve(confirm(msg));
try {
if (TG?.showConfirm) return new Promise((r) => TG.showConfirm(msg, r));
return Promise.resolve(confirm(String(msg)));
} catch (e) {
try { return Promise.resolve(confirm(String(msg))); } catch { return Promise.resolve(false); }
}
},
theme: () => TG?.themeParams || {},