Fortschrittsbalken: stetiger Creep statt fixer Sprünge
Balken kriecht jetzt asymptotisch innerhalb jeder Phase (queued 2-10%, recherche 12-30%, analyse 33-60%, faktencheck 65-92%) statt bei Phasenwechsel hart zu springen. 3% des Restwegs pro 500ms-Tick sorgt für gleichmäßige Bewegung unabhängig von der Phasendauer. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
@@ -228,6 +228,8 @@ const UI = {
|
|||||||
|
|
||||||
_progressStartTime: null,
|
_progressStartTime: null,
|
||||||
_progressTimer: null,
|
_progressTimer: null,
|
||||||
|
_progressCreepTimer: null,
|
||||||
|
_progressCurrentPercent: 0,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fortschrittsanzeige einblenden und Status setzen.
|
* Fortschrittsanzeige einblenden und Status setzen.
|
||||||
@@ -279,11 +281,25 @@ const UI = {
|
|||||||
else if (i + 1 === step.active) el.classList.add('active');
|
else if (i + 1 === step.active) el.classList.add('active');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Phasen-Bereiche für stetigen Fortschritt
|
||||||
|
const ranges = {
|
||||||
|
queued: { from: 2, to: 10 },
|
||||||
|
researching: { from: 12, to: 30 },
|
||||||
|
deep_researching: { from: 12, to: 30 },
|
||||||
|
analyzing: { from: 33, to: 60 },
|
||||||
|
factchecking: { from: 65, to: 92 },
|
||||||
|
cancelling: { from: 0, to: 5 },
|
||||||
|
};
|
||||||
|
|
||||||
|
const range = ranges[status] || ranges.queued;
|
||||||
const fill = document.getElementById('progress-fill');
|
const fill = document.getElementById('progress-fill');
|
||||||
const percent = step.active === 0 ? 5 : Math.round((step.active / 3) * 100);
|
|
||||||
if (fill) {
|
if (fill) {
|
||||||
fill.style.width = percent + '%';
|
// Nicht rückwärts gehen, mindestens auf Phasen-Start springen
|
||||||
|
this._progressCurrentPercent = Math.max(this._progressCurrentPercent, range.from);
|
||||||
|
fill.style.width = this._progressCurrentPercent + '%';
|
||||||
|
this._startProgressCreep(range.to);
|
||||||
}
|
}
|
||||||
|
const percent = Math.round(this._progressCurrentPercent);
|
||||||
|
|
||||||
// ARIA-Werte auf der Progressbar aktualisieren
|
// ARIA-Werte auf der Progressbar aktualisieren
|
||||||
bar.setAttribute('aria-valuenow', String(percent));
|
bar.setAttribute('aria-valuenow', String(percent));
|
||||||
@@ -314,6 +330,33 @@ const UI = {
|
|||||||
}, 1000);
|
}, 1000);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creep-Animation starten: Balken kriecht asymptotisch zum Ziel.
|
||||||
|
*/
|
||||||
|
_startProgressCreep(target) {
|
||||||
|
this._stopProgressCreep();
|
||||||
|
this._progressCreepTimer = setInterval(() => {
|
||||||
|
const remaining = target - this._progressCurrentPercent;
|
||||||
|
if (remaining <= 0.1) return;
|
||||||
|
// 3% des Restwegs pro Tick → asymptotisch, nie überschießend
|
||||||
|
this._progressCurrentPercent += remaining * 0.03;
|
||||||
|
const fill = document.getElementById('progress-fill');
|
||||||
|
if (fill) fill.style.width = this._progressCurrentPercent + '%';
|
||||||
|
const bar = document.getElementById('progress-bar');
|
||||||
|
if (bar) bar.setAttribute('aria-valuenow', String(Math.round(this._progressCurrentPercent)));
|
||||||
|
}, 500);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creep-Animation stoppen.
|
||||||
|
*/
|
||||||
|
_stopProgressCreep() {
|
||||||
|
if (this._progressCreepTimer) {
|
||||||
|
clearInterval(this._progressCreepTimer);
|
||||||
|
this._progressCreepTimer = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abschluss-Animation: Grüner Balken mit Summary-Text.
|
* Abschluss-Animation: Grüner Balken mit Summary-Text.
|
||||||
*/
|
*/
|
||||||
@@ -321,8 +364,10 @@ const UI = {
|
|||||||
const bar = document.getElementById('progress-bar');
|
const bar = document.getElementById('progress-bar');
|
||||||
if (!bar) return;
|
if (!bar) return;
|
||||||
|
|
||||||
// Timer stoppen
|
// Timer und Creep stoppen
|
||||||
this._stopProgressTimer();
|
this._stopProgressTimer();
|
||||||
|
this._stopProgressCreep();
|
||||||
|
this._progressCurrentPercent = 100;
|
||||||
|
|
||||||
// Alle Steps auf done
|
// Alle Steps auf done
|
||||||
['step-researching', 'step-analyzing', 'step-factchecking'].forEach(id => {
|
['step-researching', 'step-analyzing', 'step-factchecking'].forEach(id => {
|
||||||
@@ -369,8 +414,9 @@ const UI = {
|
|||||||
if (!bar) return;
|
if (!bar) return;
|
||||||
bar.style.display = 'block';
|
bar.style.display = 'block';
|
||||||
|
|
||||||
// Timer stoppen
|
// Timer und Creep stoppen
|
||||||
this._stopProgressTimer();
|
this._stopProgressTimer();
|
||||||
|
this._stopProgressCreep();
|
||||||
|
|
||||||
// Error-Klasse
|
// Error-Klasse
|
||||||
bar.classList.remove('progress-bar--complete');
|
bar.classList.remove('progress-bar--complete');
|
||||||
@@ -416,6 +462,8 @@ const UI = {
|
|||||||
bar.classList.remove('progress-bar--complete', 'progress-bar--error');
|
bar.classList.remove('progress-bar--complete', 'progress-bar--error');
|
||||||
}
|
}
|
||||||
this._stopProgressTimer();
|
this._stopProgressTimer();
|
||||||
|
this._stopProgressCreep();
|
||||||
|
this._progressCurrentPercent = 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
In neuem Issue referenzieren
Einen Benutzer sperren