diff --git a/android/src/screens/ChatScreen.tsx b/android/src/screens/ChatScreen.tsx index a119532..78977f0 100644 --- a/android/src/screens/ChatScreen.tsx +++ b/android/src/screens/ChatScreen.tsx @@ -2539,7 +2539,7 @@ const ChatScreen: React.FC = () => { Aus diesem Chat - + {specials.map(m => { if (m.memorySaved) { const ms = m.memorySaved; @@ -2595,7 +2595,12 @@ const ChatScreen: React.FC = () => { Alle Memories aus der DB - { setInboxVisible(false); setMemoryDetailId(id); }} /> + {/* flex:1 Wrapper damit MemoryBrowser den verbleibenden Platz + bekommt (sonst rendert die FlatList intern mit 0 Hoehe und + nimmt nur was der Inhalt sagt → Scroll-Gestures verschwinden). */} + + { setInboxVisible(false); setMemoryDetailId(id); }} /> + diff --git a/diagnostic/index.html b/diagnostic/index.html index 3ac186d..d4cce11 100644 --- a/diagnostic/index.html +++ b/diagnostic/index.html @@ -968,11 +968,11 @@ - + @@ -3101,6 +3109,7 @@
${detailLine}
"${escapeHtml(t.message || '')}"
+
@@ -3138,10 +3147,21 @@ document.getElementById('trigger-watcher-fields').style.display = t === 'watcher' ? '' : 'none'; } + // null = Create-Modus, string = Edit-Modus (Name der bearbeiteten Bubble) + let editingTriggerName = null; + async function openTriggerCreate() { + editingTriggerName = null; + document.getElementById('trigger-modal-title').textContent = 'Neuer Trigger'; + document.getElementById('trigger-modal-save-btn').textContent = 'Anlegen'; + document.getElementById('trigger-type').disabled = false; + document.getElementById('trigger-name').disabled = false; + document.getElementById('trigger-timer-create-fields').style.display = ''; + document.getElementById('trigger-timer-edit-fields').style.display = 'none'; document.getElementById('trigger-type').value = 'timer'; document.getElementById('trigger-name').value = ''; document.getElementById('trigger-timer-minutes').value = '10'; + document.getElementById('trigger-timer-fires-at').value = ''; document.getElementById('trigger-condition').value = ''; document.getElementById('trigger-check-interval').value = '300'; document.getElementById('trigger-throttle').value = '3600'; @@ -3170,6 +3190,52 @@ function closeTriggerModal() { document.getElementById('trigger-modal').classList.remove('open'); + editingTriggerName = null; + } + + /** Edit-Modus: Modal mit existierenden Trigger-Werten fuellen. */ + async function openTriggerEdit(name) { + const t = triggersCache.find(x => x.name === name); + if (!t) { alert('Trigger nicht in cache, lade neu...'); loadTriggers(); return; } + editingTriggerName = name; + document.getElementById('trigger-modal-title').textContent = 'Trigger bearbeiten — ' + name; + document.getElementById('trigger-modal-save-btn').textContent = 'Speichern'; + // Type + Name sind im Edit-Modus nicht aenderbar + document.getElementById('trigger-type').value = t.type; + document.getElementById('trigger-type').disabled = true; + document.getElementById('trigger-name').value = t.name; + document.getElementById('trigger-name').disabled = true; + // Timer: relative-Minutes-Feld aus, absoluter ISO-Feld an + document.getElementById('trigger-timer-create-fields').style.display = 'none'; + document.getElementById('trigger-timer-edit-fields').style.display = ''; + document.getElementById('trigger-timer-fires-at').value = t.fires_at || ''; + // Watcher-Felder vorbefuellen + document.getElementById('trigger-condition').value = t.condition || ''; + document.getElementById('trigger-check-interval').value = String(t.check_interval_sec || 300); + document.getElementById('trigger-throttle').value = String(t.throttle_sec || 3600); + document.getElementById('trigger-message').value = t.message || ''; + document.getElementById('trigger-modal-error').style.display = 'none'; + onTriggerTypeChange(); + // Variablen-Hinweis fuer Watcher auch im Edit-Modus + if (t.type === 'watcher') { + try { + const r = await fetch('/api/brain/triggers/conditions'); + const d = await r.json(); + const info = document.getElementById('trigger-vars-info'); + if (info) { + const vars = (d.variables || []).map(v => + `${escapeHtml(v.name)}=${escapeHtml(String(d.current[v.name]))} (${escapeHtml(v.desc)})` + ).join(' · '); + const fns = (d.functions || []).map(f => + `${escapeHtml(f.signature)} — ${escapeHtml(f.desc)}` + ).join('
'); + info.innerHTML = + 'Variablen: ' + vars + + (fns ? '

Funktionen:
' + fns : ''); + } + } catch {} + } + document.getElementById('trigger-modal').classList.add('open'); } async function saveTrigger() { @@ -3181,6 +3247,33 @@ if (!name) { errEl.textContent = 'Name fehlt.'; errEl.style.display = 'block'; return; } if (!message) { errEl.textContent = 'Nachricht fehlt.'; errEl.style.display = 'block'; return; } try { + // ── EDIT-MODUS ────────────────────────────────────────── + if (editingTriggerName) { + const patch = { message }; + if (ttype === 'watcher') { + const condition = document.getElementById('trigger-condition').value.trim(); + if (!condition) { errEl.textContent = 'Condition fehlt.'; errEl.style.display = 'block'; return; } + patch.condition = condition; + patch.check_interval_sec = parseInt(document.getElementById('trigger-check-interval').value, 10) || 300; + patch.throttle_sec = parseInt(document.getElementById('trigger-throttle').value, 10) || 3600; + } else if (ttype === 'timer') { + const fa = document.getElementById('trigger-timer-fires-at').value.trim(); + if (fa) patch.fires_at = fa; + } + const r = await fetch('/api/brain/triggers/' + encodeURIComponent(editingTriggerName), { + method: 'PATCH', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(patch), + }); + if (!r.ok) { + const txt = await r.text(); + throw new Error('HTTP ' + r.status + ': ' + txt.slice(0, 200)); + } + closeTriggerModal(); + loadTriggers(); + return; + } + // ── CREATE-MODUS ──────────────────────────────────────── let url, body; if (ttype === 'timer') { const mins = parseInt(document.getElementById('trigger-timer-minutes').value, 10) || 10;