fix: сброс состояния при F5/закрытии — beforeunload, abort XHR, close EventSource
Deploy drhider / validate (push) Waiting to run

This commit is contained in:
2026-07-14 19:22:36 +04:00
parent b3298b415e
commit 17bc4aebf8
2 changed files with 33 additions and 7 deletions
+1 -1
View File
@@ -20,7 +20,7 @@ if _sys_path_root not in sys.path:
sys.path.insert(0, _sys_path_root)
# Версия приложения (меняется при изменениях)
VERSION = "0.0.22"
VERSION = "0.0.23"
def create_app():
+32 -6
View File
@@ -139,6 +139,24 @@ const st = document.getElementById('status');
const db = document.getElementById('dlBtns');
let sf = [];
let currentSid = '';
let activeES = null; // активный EventSource
let activeXHR = null; // активный XHR
function resetAll() {
if (activeES) { activeES.close(); activeES = null; }
if (activeXHR) { activeXHR.abort(); activeXHR = null; }
currentSid = '';
sf = [];
fi.value = '';
rr();
st.className = '';
st.textContent = '';
db.classList.remove('show');
ub.disabled = false;
}
// При F5 / закрытии вкладки — обрубить всё
window.addEventListener('beforeunload', () => resetAll());
function fs(b) { return b < 1024 ? b + ' B' : b < 1048576 ? (b / 1024).toFixed(1) + ' KB' : (b / 1048576).toFixed(1) + ' MB'; }
@@ -158,6 +176,11 @@ function ss(idx, h) { const e = document.getElementById('st-' + idx); if (e) e.i
async function uploadFiles() {
if (sf.length === 0) return;
// Обрубить всё что могло остаться от предыдущего раза
resetAll();
ub.disabled = true;
sf = Array.from(fi.files); // восстановить список после resetAll
rr();
ub.disabled = true;
db.classList.remove('show');
const total = sf.length;
@@ -201,6 +224,7 @@ async function uploadFiles() {
};
xhr.onerror = function() { reject(new Error('Сеть')); };
xhr.ontimeout = function() { reject(new Error('Таймаут 30с')); };
activeXHR = xhr;
xhr.send(fd);
});
} catch (err) {
@@ -226,8 +250,8 @@ async function uploadFiles() {
try {
await new Promise((resolve, reject) => {
const es = new EventSource('/api/process_stream/' + currentSid);
es.addEventListener('start', function(e) {
activeES = new EventSource('/api/process_stream/' + currentSid);
activeES.addEventListener('start', function(e) {
const d = JSON.parse(e.data);
fileTimers[d.idx] = performance.now();
fileIntervals[d.idx] = setInterval(function() {
@@ -241,8 +265,9 @@ async function uploadFiles() {
const elapsed = ((performance.now() - (fileTimers[d.idx] || performance.now())) / 1000).toFixed(1);
ss(d.idx, '<span style="color:#22c55e">✓ ' + elapsed + 'с</span>');
});
es.addEventListener('complete', function(e) {
es.close();
activeES.addEventListener('complete', function(e) {
activeES.close();
activeES = null;
clearInterval(ptimer);
const d = JSON.parse(e.data);
st.className = 'status done';
@@ -250,8 +275,9 @@ async function uploadFiles() {
db.classList.add('show');
resolve();
});
es.onerror = function() {
es.close();
activeES.onerror = function() {
activeES.close();
activeES = null;
clearInterval(ptimer);
reject(new Error('SSE connection failed'));
};