Files
Aether/frontend/src/format.ts
T
marcandClaude Opus 5 e9f69f7d7f feat(uploads): Fortschritt in MB, Tempo und Restzeit; Abbruchkreuz rot
Das Kreuz faerbt sich beim Darueberfahren rot -- aber nur, solange der
Upload laeuft. Dasselbe Zeichen tut zwei Dinge: eine Meldung wegraeumen
ist folgenlos, einen laufenden Vorgang fallen zu lassen nicht.

Unter dem Balken steht jetzt "4.2 MB / 18.0 MB · 1.8 MB/s · 8 s left".
Die Zahlen kamen schon immer vom XMLHttpRequest, sie wurden nur
weggeworfen. Neu gerechnet wird nur das Tempo -- der Browser meldet
Bytes, nicht deren Ableitung.

Zwei Daempfungen, aus zwei Gruenden:

* Das Tempo aus einem einzelnen Abstand springt zwischen dem Doppelten
  und der Haelfte. Gleitender Mittelwert (0,7/0,3) ueber Messpunkte von
  mindestens 0,2 s.
* Die Anzeige wird hoechstens alle 150 ms nachgezogen. Der Browser meldet
  im 50-ms-Takt; bei drei Dateien waeren das sechzig Neuaufbauten der
  Liste je Sekunde fuer eine Zahl, die niemand so schnell liest.

Jeder Teil erscheint erst, wenn er stimmt: Groesse sofort, Tempo nach dem
zweiten Messpunkt, Restzeit erst mit beidem. Eine Schaetzung aus dem
Nichts waere schlimmer als keine -- man richtet sich danach.

formatDuration in src/format.ts, 5 Tests (37 gesamt).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 08:46:28 +02:00

46 lines
1.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Zahlen, wie ein Mensch sie liest.
*
* Stand bis hierher in `pages/FileBrowser.tsx` – und **fünf** Module holten
* sie von dort: Papierkorb, Etiketten, „Geteilt mit mir", Fassungen,
* Eigenschaften. Eine Seite als Fundort für eine Rechenfunktion heißt, dass
* jedes dieser Module am Dateibrowser hängt, samt allem, was der mitbringt.
* Zum Umbenennen einer Zahl musste man eine Seite anfassen.
*/
/**
* Byte-Zahl in Kilo, Mega, Giga.
*
* Tausend-vierundzwanzig, nicht tausend: Das ist die Einheit, in der
* Dateisysteme und Betriebssysteme rechnen – eine Datei, die dort „1,4 MB"
* heißt, soll hier nicht 1,5 heißen.
*/
export function formatBytes(n: number): string {
if (n < 1024) return `${n} B`
if (n < 1024 ** 2) return `${(n / 1024).toFixed(1)} KB`
if (n < 1024 ** 3) return `${(n / 1024 ** 2).toFixed(1)} MB`
return `${(n / 1024 ** 3).toFixed(1)} GB`
}
/**
* Eine Dauer, wie man sie beim Warten liest.
*
* Grob genug, dass die Zahl nicht zappelt, genau genug, dass sie etwas sagt:
* unter einer Minute in Sekunden, darüber als `3:07 min`. Sekunden bis in die
* zehnte Minute auszuschreiben hieße eine Zahl, die sich jede Sekunde ändert
* und trotzdem niemandem hilft.
*
* Leer bei allem, was keine Dauer ist – unendlich, negativ, keine Zahl. Der
* Aufrufer zeigt dann gar nichts an, statt „NaN s" zu schreiben.
*/
export function formatDuration(seconds: number): string {
if (!Number.isFinite(seconds) || seconds < 0) return ''
// Unter einer Sekunde bleibt "1 s" stehen: "0 s" sähe aus wie fertig,
// während der Balken noch läuft.
if (seconds < 60) return `${Math.max(1, Math.round(seconds))} s`
const total = Math.round(seconds)
const m = Math.floor(total / 60)
if (m < 60) return `${m}:${String(total % 60).padStart(2, '0')} min`
return `${Math.floor(m / 60)}:${String(m % 60).padStart(2, '0')} h`
}