Die monolithische ui.js (1534 Zeilen) zusammen mit chat.js (612) und history.js (626) in fokussierte Module aufgeteilt: Neue Dateien aus ui.js: - ui-helpers.js (126) - DOM-Utilities, $, esc, truncate, scrollDown, Toast - markdown.js (143) - renderMarkdown, wrapKreaGalleries, LaTeX/Code-Schutz - cards.js (90) - buildSessionCard, buildAgentCard - msg-actions.js (208) - Delete, Mark, Share, Reply-Button, Timestamp - tool-ui.js (332) - Tool-Boxes, Diffs, Todo-Liste, Visibility - modals.js (190) - System-Prompt, Command-Output, Krea-Image Modals - stream-ui.js (124) - Stream-Bubble, Review-Streaming - bubbles.js (312) - User/Assistant/Error/Warning/Choice/Review Bubbles Neue Dateien aus chat.js: - reply.js (54) - Reply/Quote-Handling mit pendingReply State - files.js (110) - File-Upload, Workspace-Refs mit pendingFiles/Refs State Neue Datei aus history.js: - archive.js (173) - Archiv-Loading mit loadedArchiveCount State Verbleibend: - chat.js (448) - Stream-Events, sendMessage, handleChoiceClick, Plan-Mode - history.js (464) - History laden, Polling, Message-Rendering Kein Code verändert, nur verschoben. Alle 94 Funktionen verifiziert. Globale Variablen in die Module verschoben, wo sie primär genutzt werden.
55 lines
1.6 KiB
JavaScript
55 lines
1.6 KiB
JavaScript
// ── Reply / Quote ──
|
|
|
|
let pendingReply = null; // { index, role, text } - Zitierte Nachricht
|
|
|
|
function _formatReplyTimestamp(ts) {
|
|
if (!ts) return 'Jetzt';
|
|
try {
|
|
const d = new Date(ts);
|
|
const now = new Date();
|
|
const hh = d.getHours().toString().padStart(2, '0');
|
|
const mm = d.getMinutes().toString().padStart(2, '0');
|
|
// Gleiches Datum → nur Uhrzeit, sonst Datum + Uhrzeit
|
|
if (d.toDateString() === now.toDateString()) {
|
|
return hh + ':' + mm;
|
|
}
|
|
const dd = d.getDate().toString().padStart(2, '0');
|
|
const mo = (d.getMonth() + 1).toString().padStart(2, '0');
|
|
return dd + '.' + mo + '. ' + hh + ':' + mm;
|
|
} catch { return 'Jetzt'; }
|
|
}
|
|
|
|
function setReply(reply) {
|
|
pendingReply = reply;
|
|
renderReplyPreview();
|
|
document.getElementById('input')?.focus();
|
|
}
|
|
|
|
function clearReply() {
|
|
pendingReply = null;
|
|
renderReplyPreview();
|
|
}
|
|
|
|
function renderReplyPreview() {
|
|
const container = $('#replyPreview');
|
|
if (!container) return;
|
|
|
|
if (!pendingReply) {
|
|
container.innerHTML = '';
|
|
container.hidden = true;
|
|
return;
|
|
}
|
|
|
|
const roleLabel = pendingReply.role === 'user' ? 'User' : 'Assistant';
|
|
const timeLabel = _formatReplyTimestamp(pendingReply.timestamp);
|
|
const preview = truncate(pendingReply.text, 150);
|
|
|
|
container.innerHTML = `<div class="reply-preview-item">
|
|
<span class="reply-icon"><i class="fa fa-reply"></i></span>
|
|
<span class="reply-meta">${esc(timeLabel)}, ${esc(roleLabel)}</span>
|
|
<span class="reply-text">${esc(preview)}</span>
|
|
<button class="file-remove" onclick="clearReply()"><i class="fa fa-times"></i></button>
|
|
</div>`;
|
|
container.hidden = false;
|
|
}
|