// ── Timestamp ── // formatTimestamp() → defined in ui-helpers.js function _addTimestamp(div, timestamp) { if (!timestamp) return; var formatted = formatTimestamp(timestamp); if (!formatted) return; var span = document.createElement('span'); span.className = 'msg-timestamp'; span.textContent = formatted; div.prepend(span); } // ── Delete Button ── function _addDeleteButton(div, messageId, deletedOn) { if (!messageId) return; const isDeleted = !!deletedOn; const btn = document.createElement('button'); btn.className = 'msg-delete-btn icon-btn' + (isDeleted ? ' deleted' : ''); btn.innerHTML = ''; btn.title = isDeleted ? 'Löschung aufheben' : 'Nachricht löschen'; btn.addEventListener('click', async (e) => { e.stopPropagation(); try { const result = await apiToggleMessageDelete(messageId); const nowDeleted = !!result.deletedOn; btn.classList.toggle('deleted', nowDeleted); btn.title = nowDeleted ? 'Löschung aufheben' : 'Nachricht löschen'; if (nowDeleted && !isDeletedVisible()) { // Nachricht ausblenden div.classList.add('msg-deleted-hidden'); } else { div.classList.remove('msg-deleted-hidden'); div.classList.toggle('msg-deleted', nowDeleted); } } catch (err) { console.error('Delete toggle failed:', err); } }); // Nach dem Reply-Button einfügen const replyBtn = div.querySelector('.msg-reply-btn'); if (replyBtn) { replyBtn.after(btn); } else { div.prepend(btn); } } function isDeletedVisible() { return loadSettings().showDeletedMessages === true; } // ── Mark Button ── function _addMarkButton(div, messageId, isMarked) { if (!messageId) return; // kein DB-Eintrag → kein Button const btn = document.createElement('button'); btn.className = 'msg-mark-btn icon-btn' + (isMarked ? ' marked' : ''); btn.innerHTML = isMarked ? '' : ''; btn.title = 'Als wichtig markieren'; btn.addEventListener('click', async (e) => { e.stopPropagation(); try { const result = await apiToggleMessageMark(messageId); btn.classList.toggle('marked', result.isMarked); btn.innerHTML = result.isMarked ? '' : ''; div.classList.toggle('marked', result.isMarked); } catch (err) { console.error('Mark toggle failed:', err); } }); // Nach dem Delete-Button einfügen (oder nach Reply-Button, oder am Anfang) const deleteBtn = div.querySelector('.msg-delete-btn'); if (deleteBtn) { deleteBtn.after(btn); } else { const replyBtn = div.querySelector('.msg-reply-btn'); if (replyBtn) { replyBtn.after(btn); } else { div.prepend(btn); } } } // ── Share Button ── function _addShareButton(div, messageId) { if (!messageId) return; const btn = document.createElement('button'); btn.className = 'msg-share-btn icon-btn'; btn.innerHTML = ''; btn.title = 'Nachricht teilen'; btn.addEventListener('click', async (e) => { e.stopPropagation(); try { // Kontextmenü: Einzelnachricht oder mit Kontext? const mode = await _showShareMenu(btn); if (!mode) return; // abgebrochen const result = await apiShareMessage(messageId, mode === 'context'); const url = location.origin + '/#shared/' + result.token; await navigator.clipboard.writeText(url); showToast('Link kopiert!', 'success'); } catch (err) { showToast('Fehler: ' + err.message, 'error'); } }); // Nach dem Mark-Button einfügen const markBtn = div.querySelector('.msg-mark-btn'); if (markBtn) { markBtn.after(btn); } else { const deleteBtn = div.querySelector('.msg-delete-btn'); if (deleteBtn) { deleteBtn.after(btn); } else { div.prepend(btn); } } } function _showShareMenu(anchorBtn) { return new Promise((resolve) => { // Wenn schon ein Menü offen, schließen const existing = document.querySelector('.share-menu'); if (existing) { existing.remove(); resolve(null); return; } const menu = document.createElement('div'); menu.className = 'share-menu'; menu.innerHTML = ` `; // Positionierung const rect = anchorBtn.getBoundingClientRect(); menu.style.position = 'fixed'; menu.style.top = (rect.bottom + 4) + 'px'; menu.style.left = rect.left + 'px'; menu.style.zIndex = '10000'; document.body.appendChild(menu); function cleanup() { menu.remove(); document.removeEventListener('click', outsideClick); } function outsideClick(e) { if (!menu.contains(e.target)) { cleanup(); resolve(null); } } menu.querySelectorAll('.share-menu-item').forEach(item => { item.addEventListener('click', (e) => { e.stopPropagation(); const mode = item.dataset.mode; cleanup(); resolve(mode); }); }); // Beim nächsten Klick außerhalb schließen setTimeout(() => document.addEventListener('click', outsideClick), 10); }); } // ── Reply Button ── function _addReplyButton(div) { const btn = document.createElement('button'); btn.className = 'msg-reply-btn icon-btn'; btn.innerHTML = ''; btn.title = 'Antworten'; btn.addEventListener('click', (e) => { e.stopPropagation(); // Nur den eigentlichen Nachrichten-Text holen (ohne Reply-Button-Text) const clone = div.cloneNode(true); clone.querySelectorAll('.msg-reply-btn, .attachment-indicator, .reply-quote').forEach(el => el.remove()); const text = clone.textContent.trim(); setReply({ role: div.dataset.role, timestamp: div.dataset.timestamp || '', text }); }); div.prepend(btn); }