diff --git a/config/current.ver b/config/current.ver index 457d1be..7ca8559 100644 --- a/config/current.ver +++ b/config/current.ver @@ -1 +1 @@ -1.2.44 \ No newline at end of file +1.2.45 \ No newline at end of file diff --git a/public/assets/js/bridge/blocks-api.js b/public/assets/js/bridge/blocks-api.js index 2a6d93b..93e2f75 100644 --- a/public/assets/js/bridge/blocks-api.js +++ b/public/assets/js/bridge/blocks-api.js @@ -453,6 +453,22 @@ editor.Commands.add('save-data', { run: function(editor, sender) { + const writeDebugLog = (payload) => { + try { + const base = API_KERNEL_URL || '/api.php'; + const line = JSON.stringify({ time: new Date().toISOString(), ...payload }); + fetch(base, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + action: 'debug.log.write', + name: 'ui_save_sync.log', + append: 1, + line, + }), + }).catch(() => {}); + } catch {} + }; // 💡 FIX: Sicherstellen, dass sender existiert und die 'set'-Methode hat (nur bei Buttons) if (sender && typeof sender.set === 'function') { sender.set('active', 0); // Schaltet den Button nach dem Klick ab @@ -465,6 +481,7 @@ } // Sicherstellen, dass ggf. aktive Text-Edits vor dem Speichern synchronisiert werden + let syncInfo = { stage: 'pre', active: null, selected: null, contentSynced: false }; try { const wrapper = editor.getWrapper && editor.getWrapper(); const resolveComponent = (el) => { @@ -484,22 +501,52 @@ if (!html.trim() && current.trim()) return; comp.set('content', html); comp.trigger && comp.trigger('change:content'); + syncInfo.contentSynced = true; }; const doc = editor.Canvas && editor.Canvas.getDocument ? editor.Canvas.getDocument() : null; const active = doc && doc.activeElement; + if (active) { + syncInfo.active = { + tag: active.tagName, + isEditable: !!(active.isContentEditable || (active.getAttribute && active.getAttribute('contenteditable') === 'true')), + htmlLen: (active.innerHTML || '').length, + htmlPreview: (active.innerHTML || '').slice(0, 200), + }; + } if (active && (active.isContentEditable || (active.getAttribute && active.getAttribute('contenteditable') === 'true'))) { syncElement(active); } const selected = editor.getSelected && editor.getSelected(); const view = selected && selected.view; + if (selected) { + syncInfo.selected = { + id: selected.getId ? selected.getId() : (selected.get && selected.get('id')), + type: selected.get ? selected.get('type') : null, + contentLen: selected.get ? String(selected.get('content') || '').length : 0, + }; + } if (view && view.el && (view.el.isContentEditable || (view.el.getAttribute && view.el.getAttribute('contenteditable') === 'true'))) { syncElement(view.el); } else if (selected && typeof selected.is === 'function' && (selected.is('text') || selected.is('textnode')) && view && view.el) { syncElement(view.el); } + syncInfo.stage = 'post'; + writeDebugLog({ + event: 'save:sync', + entityId: CURRENT_ENTITY_ID, + sectionId: SECTION_ID || null, + syncInfo, + editorHtmlLen: (editor.getHtml && String(editor.getHtml() || '').length) || 0, + editorCssLen: (editor.getCss && String(editor.getCss() || '').length) || 0, + }); } catch (e) { + writeDebugLog({ + event: 'save:sync:error', + entityId: CURRENT_ENTITY_ID, + error: String(e && e.message ? e.message : e), + }); // kein Block, falls Sync nicht moeglich } diff --git a/public/assets/js/ui-editor.js b/public/assets/js/ui-editor.js index 593fc3c..9bc494a 100644 --- a/public/assets/js/ui-editor.js +++ b/public/assets/js/ui-editor.js @@ -70,6 +70,8 @@ export function initEditor() { let lastSelectionInfo = null; const debugUiLog = (payload) => { + // Deaktiviert auf Wunsch (Log-Datei ui_editor_dirty.log soll nicht mehr geschrieben werden) + return; const now = Date.now(); const key = payload && payload.event ? payload.event : 'log'; if (now - lastDebugTs < 400 && key === lastDebugKey) return;