fix: Speichern-Dialog zeigt auf die Originaldatei statt auf einen „(1)"-Nachbarn (D74-Nachtrag)
Mit bekanntem, aber nicht beschreibbarem Handle bekommt showSaveFilePicker startIn + den exakten Dateinamen; ohne Handle teilen sich Öffnen und Speichern eine Picker-id, damit der Dialog im Plan-Ordner aufgeht statt in Downloads. Der Abbruch-Kreislauf (Dialog schlägt Falsches vor -> Abbruch -> kein Handle gemerkt -> wieder Dialog) ist damit durchbrochen. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
532bbace21
commit
731a383345
@@ -19,6 +19,7 @@ reverse.
|
|||||||
|
|
||||||
## 2026-08-25
|
## 2026-08-25
|
||||||
|
|
||||||
|
- Fix: the save dialog suggested a "name (1)" neighbour in the wrong folder — it now points at the original file, and open/save dialogs remember the plan folder
|
||||||
- Ctrl+S saves the document as a file — with a remembered file it writes straight back in place, and the document name flashes as confirmation
|
- Ctrl+S saves the document as a file — with a remembered file it writes straight back in place, and the document name flashes as confirmation
|
||||||
- Fix: a file double-clicked right after the app starts could open as a duplicate document instead of updating its own
|
- Fix: a file double-clicked right after the app starts could open as a duplicate document instead of updating its own
|
||||||
- The installed app registers for `.werkbaum` files — a double-click in the file manager opens them straight into the editor
|
- The installed app registers for `.werkbaum` files — a double-click in the file manager opens them straight into the editor
|
||||||
|
|||||||
@@ -5543,3 +5543,47 @@ Petrol-Haken am Dokumentnamen hat erst ein synthetischer Strg+S nach 400 ms
|
|||||||
gezeigt (Klasse `done`, ✓, `#0F766E`): Der Werkzeug-Umlauf ist langsamer als
|
gezeigt (Klasse `done`, ✓, `#0F766E`): Der Werkzeug-Umlauf ist langsamer als
|
||||||
die 1,5 s des Blitzes — eine Messgrenze, kein Befund. Die Legende zeigt die
|
die 1,5 s des Blitzes — eine Messgrenze, kein Befund. Die Legende zeigt die
|
||||||
neue Zeile in DE und EN.
|
neue Zeile in DE und EN.
|
||||||
|
|
||||||
|
**Nachtrag — der Speichern-Dialog zeigt jetzt auf die Originaldatei.**
|
||||||
|
Gemeldet: „beim Ctrl-S erscheint immer ein Dialog und der Dateiname mit (1)
|
||||||
|
dahinter, ich möchte aber direkt speichern." Der Befund hat zwei Schichten:
|
||||||
|
|
||||||
|
- **„Immer ein Dialog" ist der Abbruch-Kreislauf.** Ein Handle wird erst nach
|
||||||
|
einem **abgeschlossenen** Dialog gemerkt (D72-Nachtrag) — wer den Dialog
|
||||||
|
abbricht, steht beim nächsten Strg+S wieder davor. Abgebrochen wird er zu
|
||||||
|
Recht, wenn er das Falsche vorschlägt, und genau das tat er:
|
||||||
|
- **Das „(1)" ist Chromiums Ausweich-Vorschlag.** `showSaveFilePicker` öffnet
|
||||||
|
ohne weitere Angaben im zuletzt benutzten Ordner und macht aus dem
|
||||||
|
Namensvorschlag einen „name (1)"-Nachbarn, wenn dort schon eine gleichnamige
|
||||||
|
Datei liegt. Wer **den** bestätigt, speichert an der falschen Stelle — der
|
||||||
|
Dialog lud also zum Fehler ein und zum Abbruch gleichermaßen.
|
||||||
|
|
||||||
|
Zwei Handgriffe, beide am Picker-Aufruf:
|
||||||
|
|
||||||
|
- **Mit bekanntem, aber nicht beschreibbarem Handle** (der Fall „Berechtigung
|
||||||
|
verweigert" oder ein gescheiterter Schreibversuch) bekommt der Dialog
|
||||||
|
`startIn: <handle>` und den **exakten Dateinamen** des Handles: Er öffnet im
|
||||||
|
Ordner der Originaldatei mit ihrem Namen. Einmal Ersetzen bestätigen, und
|
||||||
|
das neue Handle ist beschreibbar — jedes weitere Strg+S ist still.
|
||||||
|
- **Ohne bekanntes Handle** teilen sich Öffnen- und Speichern-Dialog eine
|
||||||
|
Picker-`id` (`werkbaum-files`): Chromium merkt sich je id den zuletzt
|
||||||
|
benutzten Ordner, der Speichern-Dialog geht also dort auf, wo zuletzt
|
||||||
|
geöffnet wurde — statt in Downloads. Kein `id` im startIn-Fall: Ein
|
||||||
|
gemerkter Ordner überstimmte sonst das startIn.
|
||||||
|
|
||||||
|
Dazu gehört die Einordnung, die kein Code ändern kann: Der **erste** Strg+S
|
||||||
|
je Datei zeigt ohne beschreibbares Handle rechtens einen Dialog (die API
|
||||||
|
verlangt es), und nach einem App-Neustart fragt der Browser einmal nach der
|
||||||
|
Schreibberechtigung — „Bei jedem Besuch zulassen" der installierten App
|
||||||
|
räumt auch das ab. Direkt heißt: ab dem zweiten Mal.
|
||||||
|
|
||||||
|
**Nachgemessen** (dist, Picker gestubbt): Ohne Handle trägt der Aufruf
|
||||||
|
`suggestedName: "Example.werkbaum"` und `id: "werkbaum-files"`; mit
|
||||||
|
verweigertem Handle (`queryPermission → 'denied'`) trägt er den exakten
|
||||||
|
Handle-Namen und `startIn` = genau dieses Handle, ohne `id`; nach dem
|
||||||
|
Dialog wird geschrieben. Wegwerf-Dokument über die echte UI angelegt und
|
||||||
|
gelöscht (übrig: Example, Werkbaum). Ob der Nutzer zusätzlich noch das
|
||||||
|
**alte, vor dem Deploy geöffnete PWA-Fenster** vor sich hatte (dort gab es
|
||||||
|
den Strg+S-Handler noch nicht — die Taste ging an den Browser, dessen
|
||||||
|
„Seite speichern" hängt bei Wiederholung ebenfalls „ (1)" an), ließ sich
|
||||||
|
von hier nicht feststellen; ein Neustart der App stellt es klar.
|
||||||
|
|||||||
+19
-2
@@ -3977,7 +3977,10 @@ async function adoptFile(handle, name, text){
|
|||||||
}
|
}
|
||||||
async function openWithPicker(){
|
async function openWithPicker(){
|
||||||
let handle;
|
let handle;
|
||||||
try{ [handle] = await window.showOpenFilePicker({types: FILE_TYPES}); }
|
/* id: Chromium merkt sich je Picker-id den zuletzt benutzten Ordner —
|
||||||
|
Öffnen und handle-loses Speichern teilen sich eine, damit beide Dialoge
|
||||||
|
im Plan-Ordner aufgehen statt in Downloads (D74-Nachtrag). */
|
||||||
|
try{ [handle] = await window.showOpenFilePicker({types: FILE_TYPES, id: 'werkbaum-files'}); }
|
||||||
catch(_){ return; } /* Abbruch des Dialogs */
|
catch(_){ return; } /* Abbruch des Dialogs */
|
||||||
let text;
|
let text;
|
||||||
try{ text = await (await handle.getFile()).text(); }catch(_){ return; }
|
try{ text = await (await handle.getFile()).text(); }catch(_){ return; }
|
||||||
@@ -4008,9 +4011,23 @@ async function saveToKnownFile(d){
|
|||||||
}catch(_){ return false; }
|
}catch(_){ return false; }
|
||||||
}
|
}
|
||||||
async function saveWithPicker(d){
|
async function saveWithPicker(d){
|
||||||
|
/* Der Dialog zeigt auf die ORIGINALDATEI, wenn wir eine kennen (Handle
|
||||||
|
vorhanden, aber nicht beschreibbar — etwa nach verweigerter
|
||||||
|
Berechtigung): startIn öffnet in ihrem Ordner, suggestedName ist ihr
|
||||||
|
exakter Name. Ohne das schlägt Chromium im zuletzt benutzten Ordner
|
||||||
|
einen „name (1)"-Nachbarn vor — wer den abbricht, bekommt den Dialog
|
||||||
|
bei jedem Strg+S wieder, denn gemerkt wird ein Handle erst nach einem
|
||||||
|
ABGESCHLOSSENEN Dialog. Wer die Originaldatei wählt und das Ersetzen
|
||||||
|
bestätigt, hat ein beschreibbares Handle — jedes weitere Strg+S ist
|
||||||
|
still. Ohne bekanntes Handle hilft die geteilte Picker-id (siehe
|
||||||
|
openWithPicker). D74-Nachtrag. */
|
||||||
|
const known = fileHandles.get(d.id);
|
||||||
|
const opts = known
|
||||||
|
? {suggestedName: known.name, startIn: known, types: FILE_TYPES}
|
||||||
|
: {suggestedName: saveFileName(d.name), types: FILE_TYPES, id: 'werkbaum-files'};
|
||||||
let handle;
|
let handle;
|
||||||
try{
|
try{
|
||||||
handle = await window.showSaveFilePicker({suggestedName: saveFileName(d.name), types: FILE_TYPES});
|
handle = await window.showSaveFilePicker(opts);
|
||||||
}catch(_){ return; } /* Abbruch: bewusst kein Download hinterher */
|
}catch(_){ return; } /* Abbruch: bewusst kein Download hinterher */
|
||||||
try{ await writeToHandle(handle, d.text); }catch(_){ return; }
|
try{ await writeToHandle(handle, d.text); }catch(_){ return; }
|
||||||
fileHandles.set(d.id, handle);
|
fileHandles.set(d.id, handle);
|
||||||
|
|||||||
Reference in New Issue
Block a user