File-Explorer: Editor editierbar + Speichern-Button

This commit is contained in:
Meleki committed 2026-02-28 16:49:15 +01:00
1 parent f74409dd89
commit b84dff6d8c
3 files changed
+157 -8

No files matched your search

+79 -8
View File
@@ -41,7 +41,10 @@ function openFileExplorer(opts = {}) {
</div>
<div class="fe-footer" id="feFooter" hidden>
<span class="fe-info" id="feInfo"></span>
<button class="fe-btn fe-select-btn" id="feSelectBtn">Einfügen</button>
<div class="fe-footer-actions">
<button class="fe-btn fe-save-btn" id="feSaveBtn" disabled hidden>Speichern</button>
<button class="fe-btn fe-select-btn" id="feSelectBtn">Einfügen</button>
</div>
</div>
`;
@@ -51,6 +54,7 @@ function openFileExplorer(opts = {}) {
document.getElementById('feBack').addEventListener('click', feGoBack);
document.getElementById('feClose').addEventListener('click', closeFileExplorer);
document.getElementById('feSelectBtn').addEventListener('click', feDoSelect);
document.getElementById('feSaveBtn').addEventListener('click', feDoSave);
// ESC
_feState._keyHandler = (e) => { if (e.key === 'Escape') closeFileExplorer(); };
@@ -220,6 +224,12 @@ async function feSelectFile(entry, itemEl) {
}
info.textContent = `${data.path} — ${data.lineCount} Zeilen, ${formatSize(data.size)}`;
const saveBtn = document.getElementById('feSaveBtn');
const selectBtn = document.getElementById('feSelectBtn');
saveBtn.hidden = false;
saveBtn.disabled = true;
selectBtn.hidden = !_feState.onSelect;
footer.hidden = false;
} catch (e) {
@@ -239,22 +249,25 @@ function feDestroyEditor() {
}
function feInitCodeMirror(container, data, ext) {
container.innerHTML = '<div class="fe-cm-wrap"><textarea id="feCmTextarea"></textarea></div>';
const textarea = document.getElementById('feCmTextarea');
textarea.value = data.content;
container.innerHTML = '<div class="fe-cm-wrap"><div id="feCmHost"></div></div>';
const host = document.getElementById('feCmHost');
const mode = getCmMode(ext);
const originalContent = data.content;
const cm = CodeMirror.fromTextArea(textarea, {
const cm = CodeMirror(host, {
value: data.content,
mode: mode,
theme: 'default',
lineNumbers: true,
readOnly: true,
readOnly: false,
lineWrapping: false,
tabSize: 4,
indentWithTabs: false,
extraKeys: {}
extraKeys: {
'Ctrl-S': () => feDoSave(),
'Cmd-S': () => feDoSave()
}
});
// Selektion-Tracking für Zeilen-Info
@@ -263,6 +276,15 @@ function feInitCodeMirror(container, data, ext) {
feUpdateSelectionInfo(cm, data);
});
// Änderungs-Tracking
cm.on('change', () => {
const saveBtn = document.getElementById('feSaveBtn');
if (saveBtn) saveBtn.disabled = cm.getValue() === originalContent;
});
// Refresh nötig wenn CM in einem Container ohne finale Größe initialisiert wird
requestAnimationFrame(() => cm.refresh());
_feState._editor = cm;
_feState._editorType = 'codemirror';
}
@@ -374,6 +396,55 @@ function feDoSelect() {
closeFileExplorer();
}
async function feDoSave() {
if (!_feState || !_feState.selectedFile) return;
const cm = feGetCm();
if (!cm) return;
const saveBtn = document.getElementById('feSaveBtn');
if (saveBtn && saveBtn.disabled) return;
const content = cm.getValue();
const path = _feState.selectedFile.path;
if (saveBtn) {
saveBtn.disabled = true;
saveBtn.textContent = 'Speichern...';
}
try {
const resp = await fetch(
`/api/workspace/file?sessionId=${_feState.sessionId}&path=${encodeURIComponent(path)}`,
{ method: 'PUT', body: content }
);
if (!resp.ok) {
const err = await resp.json().catch(() => ({}));
alert('Fehler beim Speichern: ' + (err.error || resp.status));
if (saveBtn) { saveBtn.disabled = false; saveBtn.textContent = 'Speichern'; }
return;
}
const result = await resp.json();
// State aktualisieren
_feState.selectedFile.content = content;
_feState.selectedFile.size = result.size;
_feState.selectedFile.lineCount = result.lineCount;
const info = document.getElementById('feInfo');
if (info) info.textContent = `${path} — ${result.lineCount} Zeilen, ${formatSize(result.size)}`;
if (saveBtn) { saveBtn.textContent = 'Speichern'; }
// bleibt disabled, da gespeicherter Stand == aktueller Stand
} catch (e) {
alert('Netzwerk-Fehler beim Speichern');
if (saveBtn) { saveBtn.disabled = false; saveBtn.textContent = 'Speichern'; }
}
}
// ── Folder Browser Mode ──
// Nutzt /api/workspace/browse mit absolutem Pfad, zum Ordner-Auswählen.