Drop the Strg+V hint: PC gets drag-and-drop and file picker only

Ctrl+V does not reach the dialog either - Chrome only delivers a paste
gesture when there is a paste target, and the dialog has no input field.
So the shortcut is no longer mentioned anywhere; the computer now offers
exactly two routes, dragging and the file picker, and the phone keeps the
clipboard button. The paste listener stays as a silent bonus for browsers
that do deliver the event, and the now-orphaned tastenkuerzelEinfuegen()
is gone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-17 00:44:05 +02:00
parent e5e82b3634
commit 91dfd4807a
5 changed files with 64 additions and 54 deletions
+8
View File
@@ -1194,6 +1194,14 @@ wraps the web app for iPhone; a PWA home-screen install is the accepted intermed
stark eingeschränkt (sonst könnte jede Seite still mitlesen, was zuletzt kopiert wurde). stark eingeschränkt (sonst könnte jede Seite still mitlesen, was zuletzt kopiert wurde).
Live geprüft: Desktop zeigt nur noch "Datei auswählen [primaer]"/"Abbrechen", Mobil (375px, Live geprüft: Desktop zeigt nur noch "Datei auswählen [primaer]"/"Abbrechen", Mobil (375px,
`pointer: coarse`) weiterhin alle drei Knöpfe. `pointer: coarse`) weiterhin alle drei Knöpfe.
(4) **Auch Strg+V half am Rechner nicht** - vom Nutzer getestet und zurückgemeldet ("ctrl+v
doesnt work either, pc doesnt know where to paste"). Stimmt: Chrome stellt eine Einfüge-Geste
nur zu, wenn es ein Einfüge-Ziel gibt (Eingabefeld/contenteditable), und das Fenster hat
keines. Der Hinweis ist deshalb überall entfernt; am Rechner heißt es jetzt schlicht "PDF
hierher ziehen / oder unten auswählen", am Telefon "Beleg einfügen / das aus der Mail
kopierte PDF". Der `paste`-Listener bleibt als stille Zugabe für Browser, die das Ereignis
doch zustellen, wird aber nirgends mehr beworben; `tastenkuerzelEinfuegen()` wurde damit
verwaist und ist entfernt. **Am Rechner also bewusst nur zwei Wege: Ziehen und Dateiauswahl.**
- [x] Preis je Liter überall auf 2 Nachkommastellen (2026-08-17, Nutzerwunsch: "€/l for gas is - [x] Preis je Liter überall auf 2 Nachkommastellen (2026-08-17, Nutzerwunsch: "€/l for gas is
common to be displayed as x,xx €/l") — alle sieben Stellen von `de(..., 3)` auf `de(..., 2)` common to be displayed as x,xx €/l") — alle sieben Stellen von `de(..., 3)` auf `de(..., 2)`
umgestellt: Jahres- und Monatsschnitt in der Tankliste, Zeilenwert je Tankvorgang, "Preis je umgestellt: Jahres- und Monatsschnitt in der Tankliste, Zeilenwert je Tankvorgang, "Preis je
@@ -3046,22 +3046,15 @@ function belegPopupSchliessenUndLaden(datei) {
} }
/* Telefon-Weg: das aus der Mail kopierte PDF liegt in der Zwischenablage. /* Telefon-Weg: das aus der Mail kopierte PDF liegt in der Zwischenablage.
navigator.clipboard.read() ist der einzige Weg, ohne dass der Nutzer in ein navigator.clipboard.read() ist dort der einzige Weg, ohne dass der Nutzer
Eingabefeld tippen muss - iOS zeigt dafür seine eigene Einfügen-Abfrage. in ein Eingabefeld tippen muss - iOS zeigt dafür seine eigene
Einfügen-Abfrage. Der Knopf erscheint deshalb nur auf Tippgeräten, siehe
WICHTIG (Ursache eines gemeldeten Fehlers): Am Rechner hilft dieser Knopf zwischenablageKnopfSinnvoll(). */
bei einer im Explorer/Finder kopierten Datei NICHT. clipboard.read() gibt
laut Spezifikation nur Text, HTML und Bilder heraus - eine kopierte
PDF-Datei taucht dort gar nicht auf, egal wie frisch sie ist. Der Weg, der
dort funktioniert, ist Strg+V: das paste-Ereignis trägt die echte Datei in
clipboardData.files. Deshalb sagt die Meldung unten genau das, statt
pauschal "kein PDF" zu behaupten. */
async function belegAusZwischenablage() { async function belegAusZwischenablage() {
const ctx = belegPopup; const ctx = belegPopup;
if (!ctx) return; if (!ctx) return;
const strgVHinweis = `Am Rechner kann der Browser eine kopierte Datei nur über ${tastenkuerzelEinfuegen()} entgegennehmen - bitte so einfügen oder das PDF hineinziehen.`;
if (!navigator.clipboard || !navigator.clipboard.read) { if (!navigator.clipboard || !navigator.clipboard.read) {
belegPopup.fehler = strgVHinweis; belegPopup.fehler = "Dieser Browser gibt die Zwischenablage nicht heraus - bitte \"Datei auswählen\".";
render(); return; render(); return;
} }
try { try {
@@ -3069,37 +3062,41 @@ async function belegAusZwischenablage() {
const typ = (eintrag.types || []).find((t) => t === "application/pdf"); const typ = (eintrag.types || []).find((t) => t === "application/pdf");
if (typ) { belegPopupSchliessenUndLaden(new File([await eintrag.getType(typ)], "beleg.pdf", { type: "application/pdf" })); return; } if (typ) { belegPopupSchliessenUndLaden(new File([await eintrag.getType(typ)], "beleg.pdf", { type: "application/pdf" })); return; }
} }
belegPopup.fehler = strgVHinweis; belegPopup.fehler = "In der Zwischenablage liegt kein PDF - bitte den Beleg erneut kopieren oder \"Datei auswählen\".";
} catch (err) { } catch (err) {
belegPopup.fehler = "Kein Zugriff auf die Zwischenablage. " + strgVHinweis; belegPopup.fehler = "Kein Zugriff auf die Zwischenablage - bitte \"Datei auswählen\".";
} }
render(); render();
} }
function tastenkuerzelEinfuegen() { /* Der Einfügen-Knopf wird nur auf Tippgeräten angeboten. Am Rechner scheitert
return /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent) ? "Cmd+V" : "Strg+V"; er zwangsläufig: clipboard.read() gibt aus Datenschutzgründen nur Text,
} HTML und Bilder heraus, eine im Explorer kopierte Datei taucht dort nie
auf. Und das Tastenkürzel Strg+V hilft dort ebenfalls nicht - ohne
/* Der Einfügen-Knopf wird nur auf Tippgeräten angeboten. Am Rechner kann er Eingabefeld im Fenster hat der Browser kein Ziel für die Einfüge-Geste
aus Datenschutzgründen prinzipiell nicht funktionieren (clipboard.read() (vom Nutzer bestätigt). Am Rechner bleiben daher Ziehen und Dateiauswahl. */
gibt Dateien nie heraus, siehe oben) - ein Knopf, der dort zwangsläufig
scheitert, führt nur in eine Sackgasse. Dort bleiben Ziehen und Strg+V. */
function zwischenablageKnopfSinnvoll() { function zwischenablageKnopfSinnvoll() {
return window.matchMedia && window.matchMedia("(pointer: coarse)").matches; return window.matchMedia && window.matchMedia("(pointer: coarse)").matches;
} }
function vBelegPopup() { function vBelegPopup() {
if (!belegPopup) return ""; if (!belegPopup) return "";
// Am Telefon ist Einfügen der Hauptweg (PDF aus der Mail kopiert), am
// Rechner Ziehen bzw. Dateiauswahl. Strg+V wird am Rechner bewusst NICHT
// mehr angeboten: ohne Eingabefeld im Fenster hat der Browser kein Ziel für
// die Einfüge-Geste, das Tastenkürzel läuft dort also ins Leere.
const telefon = zwischenablageKnopfSinnvoll();
return `<div class="beleg-catcher" data-belegzu></div> return `<div class="beleg-catcher" data-belegzu></div>
<div class="beleg-popup" role="dialog" aria-modal="true" aria-label="Beleg hochladen"> <div class="beleg-popup" role="dialog" aria-modal="true" aria-label="Beleg hochladen">
<span class="label">Beleg hochladen</span> <span class="label">Beleg hochladen</span>
<div class="beleg-drop" id="belegDrop"> <div class="beleg-drop" id="belegDrop">
<strong>PDF hierher ziehen</strong> ${telefon
<span>oder mit ${tastenkuerzelEinfuegen()} einfügen</span> ? `<strong>Beleg einfügen</strong><span>das aus der Mail kopierte PDF</span>`
: `<strong>PDF hierher ziehen</strong><span>oder unten auswählen</span>`}
</div> </div>
${belegPopup.fehler ? `<span class="label" style="margin-top:10px;color:var(--red)">${esc(belegPopup.fehler)}</span>` : ""} ${belegPopup.fehler ? `<span class="label" style="margin-top:10px;color:var(--red)">${esc(belegPopup.fehler)}</span>` : ""}
${zwischenablageKnopfSinnvoll() ? `<button class="aktion primaer" data-belegeinfuegen>Aus Zwischenablage einfügen</button>` : ""} ${telefon ? `<button class="aktion primaer" data-belegeinfuegen>Aus Zwischenablage einfügen</button>` : ""}
<button class="aktion ${zwischenablageKnopfSinnvoll() ? "" : "primaer"}" data-belegdatei>Datei auswählen</button> <button class="aktion ${telefon ? "" : "primaer"}" data-belegdatei>Datei auswählen</button>
<button class="aktion" data-belegzu>Abbrechen</button> <button class="aktion" data-belegzu>Abbrechen</button>
</div>`; </div>`;
} }
@@ -3407,6 +3404,10 @@ function ereignisseVerdrahten() {
belegPopup.fehler = "Das war kein PDF."; belegPopup.fehler = "Das war kein PDF.";
render(); render();
}); });
/* Zugabe, kein beworbener Weg: wo der Browser eine Einfüge-Geste ohne
Eingabefeld überhaupt zustellt, wird sie mitgenommen. Am Rechner tut
Chrome das nicht (deshalb steht Strg+V nirgends mehr als Hinweis), es
kostet aber nichts, das Ereignis trotzdem anzunehmen. */
document.addEventListener("paste", (e) => { document.addEventListener("paste", (e) => {
if (!belegPopup) return; if (!belegPopup) return;
const datei = belegAusDateiliste(e.clipboardData && e.clipboardData.files); const datei = belegAusDateiliste(e.clipboardData && e.clipboardData.files);
@@ -1 +1 @@
{"version": 1786919856} {"version": 1786920185}
+27 -26
View File
@@ -3046,22 +3046,15 @@ function belegPopupSchliessenUndLaden(datei) {
} }
/* Telefon-Weg: das aus der Mail kopierte PDF liegt in der Zwischenablage. /* Telefon-Weg: das aus der Mail kopierte PDF liegt in der Zwischenablage.
navigator.clipboard.read() ist der einzige Weg, ohne dass der Nutzer in ein navigator.clipboard.read() ist dort der einzige Weg, ohne dass der Nutzer
Eingabefeld tippen muss - iOS zeigt dafür seine eigene Einfügen-Abfrage. in ein Eingabefeld tippen muss - iOS zeigt dafür seine eigene
Einfügen-Abfrage. Der Knopf erscheint deshalb nur auf Tippgeräten, siehe
WICHTIG (Ursache eines gemeldeten Fehlers): Am Rechner hilft dieser Knopf zwischenablageKnopfSinnvoll(). */
bei einer im Explorer/Finder kopierten Datei NICHT. clipboard.read() gibt
laut Spezifikation nur Text, HTML und Bilder heraus - eine kopierte
PDF-Datei taucht dort gar nicht auf, egal wie frisch sie ist. Der Weg, der
dort funktioniert, ist Strg+V: das paste-Ereignis trägt die echte Datei in
clipboardData.files. Deshalb sagt die Meldung unten genau das, statt
pauschal "kein PDF" zu behaupten. */
async function belegAusZwischenablage() { async function belegAusZwischenablage() {
const ctx = belegPopup; const ctx = belegPopup;
if (!ctx) return; if (!ctx) return;
const strgVHinweis = `Am Rechner kann der Browser eine kopierte Datei nur über ${tastenkuerzelEinfuegen()} entgegennehmen - bitte so einfügen oder das PDF hineinziehen.`;
if (!navigator.clipboard || !navigator.clipboard.read) { if (!navigator.clipboard || !navigator.clipboard.read) {
belegPopup.fehler = strgVHinweis; belegPopup.fehler = "Dieser Browser gibt die Zwischenablage nicht heraus - bitte \"Datei auswählen\".";
render(); return; render(); return;
} }
try { try {
@@ -3069,37 +3062,41 @@ async function belegAusZwischenablage() {
const typ = (eintrag.types || []).find((t) => t === "application/pdf"); const typ = (eintrag.types || []).find((t) => t === "application/pdf");
if (typ) { belegPopupSchliessenUndLaden(new File([await eintrag.getType(typ)], "beleg.pdf", { type: "application/pdf" })); return; } if (typ) { belegPopupSchliessenUndLaden(new File([await eintrag.getType(typ)], "beleg.pdf", { type: "application/pdf" })); return; }
} }
belegPopup.fehler = strgVHinweis; belegPopup.fehler = "In der Zwischenablage liegt kein PDF - bitte den Beleg erneut kopieren oder \"Datei auswählen\".";
} catch (err) { } catch (err) {
belegPopup.fehler = "Kein Zugriff auf die Zwischenablage. " + strgVHinweis; belegPopup.fehler = "Kein Zugriff auf die Zwischenablage - bitte \"Datei auswählen\".";
} }
render(); render();
} }
function tastenkuerzelEinfuegen() { /* Der Einfügen-Knopf wird nur auf Tippgeräten angeboten. Am Rechner scheitert
return /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent) ? "Cmd+V" : "Strg+V"; er zwangsläufig: clipboard.read() gibt aus Datenschutzgründen nur Text,
} HTML und Bilder heraus, eine im Explorer kopierte Datei taucht dort nie
auf. Und das Tastenkürzel Strg+V hilft dort ebenfalls nicht - ohne
/* Der Einfügen-Knopf wird nur auf Tippgeräten angeboten. Am Rechner kann er Eingabefeld im Fenster hat der Browser kein Ziel für die Einfüge-Geste
aus Datenschutzgründen prinzipiell nicht funktionieren (clipboard.read() (vom Nutzer bestätigt). Am Rechner bleiben daher Ziehen und Dateiauswahl. */
gibt Dateien nie heraus, siehe oben) - ein Knopf, der dort zwangsläufig
scheitert, führt nur in eine Sackgasse. Dort bleiben Ziehen und Strg+V. */
function zwischenablageKnopfSinnvoll() { function zwischenablageKnopfSinnvoll() {
return window.matchMedia && window.matchMedia("(pointer: coarse)").matches; return window.matchMedia && window.matchMedia("(pointer: coarse)").matches;
} }
function vBelegPopup() { function vBelegPopup() {
if (!belegPopup) return ""; if (!belegPopup) return "";
// Am Telefon ist Einfügen der Hauptweg (PDF aus der Mail kopiert), am
// Rechner Ziehen bzw. Dateiauswahl. Strg+V wird am Rechner bewusst NICHT
// mehr angeboten: ohne Eingabefeld im Fenster hat der Browser kein Ziel für
// die Einfüge-Geste, das Tastenkürzel läuft dort also ins Leere.
const telefon = zwischenablageKnopfSinnvoll();
return `<div class="beleg-catcher" data-belegzu></div> return `<div class="beleg-catcher" data-belegzu></div>
<div class="beleg-popup" role="dialog" aria-modal="true" aria-label="Beleg hochladen"> <div class="beleg-popup" role="dialog" aria-modal="true" aria-label="Beleg hochladen">
<span class="label">Beleg hochladen</span> <span class="label">Beleg hochladen</span>
<div class="beleg-drop" id="belegDrop"> <div class="beleg-drop" id="belegDrop">
<strong>PDF hierher ziehen</strong> ${telefon
<span>oder mit ${tastenkuerzelEinfuegen()} einfügen</span> ? `<strong>Beleg einfügen</strong><span>das aus der Mail kopierte PDF</span>`
: `<strong>PDF hierher ziehen</strong><span>oder unten auswählen</span>`}
</div> </div>
${belegPopup.fehler ? `<span class="label" style="margin-top:10px;color:var(--red)">${esc(belegPopup.fehler)}</span>` : ""} ${belegPopup.fehler ? `<span class="label" style="margin-top:10px;color:var(--red)">${esc(belegPopup.fehler)}</span>` : ""}
${zwischenablageKnopfSinnvoll() ? `<button class="aktion primaer" data-belegeinfuegen>Aus Zwischenablage einfügen</button>` : ""} ${telefon ? `<button class="aktion primaer" data-belegeinfuegen>Aus Zwischenablage einfügen</button>` : ""}
<button class="aktion ${zwischenablageKnopfSinnvoll() ? "" : "primaer"}" data-belegdatei>Datei auswählen</button> <button class="aktion ${telefon ? "" : "primaer"}" data-belegdatei>Datei auswählen</button>
<button class="aktion" data-belegzu>Abbrechen</button> <button class="aktion" data-belegzu>Abbrechen</button>
</div>`; </div>`;
} }
@@ -3407,6 +3404,10 @@ function ereignisseVerdrahten() {
belegPopup.fehler = "Das war kein PDF."; belegPopup.fehler = "Das war kein PDF.";
render(); render();
}); });
/* Zugabe, kein beworbener Weg: wo der Browser eine Einfüge-Geste ohne
Eingabefeld überhaupt zustellt, wird sie mitgenommen. Am Rechner tut
Chrome das nicht (deshalb steht Strg+V nirgends mehr als Hinweis), es
kostet aber nichts, das Ereignis trotzdem anzunehmen. */
document.addEventListener("paste", (e) => { document.addEventListener("paste", (e) => {
if (!belegPopup) return; if (!belegPopup) return;
const datei = belegAusDateiliste(e.clipboardData && e.clipboardData.files); const datei = belegAusDateiliste(e.clipboardData && e.clipboardData.files);
@@ -1 +1 @@
{"version": 1786919856} {"version": 1786920185}