File-Refs als Preview-Tags statt inline Text, fullText-Kollision fix, hidden-Override fix
This commit is contained in:
1 parent
491d3b916e
commit
4e3d92ff9f
4 files changed
+99
-10
No files matched your search
@@ -98,6 +98,40 @@
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
/* Workspace Refs */
|
||||
|
||||
.ref-preview {
|
||||
padding: var(--s2) var(--s4);
|
||||
background: var(--f1-bg);
|
||||
border-top: var(--border-width) solid var(--f1-border);
|
||||
flex-wrap: wrap;
|
||||
gap: var(--s2);
|
||||
}
|
||||
|
||||
.ref-preview:not([hidden]) {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.ref-preview-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--s2);
|
||||
padding: var(--s1) var(--s2);
|
||||
background: var(--f2-bg);
|
||||
border: var(--border-width) solid var(--f2-border);
|
||||
}
|
||||
|
||||
.ref-icon {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.ref-label {
|
||||
font-size: 0.9em;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* File Upload */
|
||||
|
||||
.file-btn {
|
||||
|
||||
@@ -123,6 +123,7 @@
|
||||
</header>
|
||||
<div class="meta-bar" id="meta"></div>
|
||||
<div id="chat"></div>
|
||||
<div id="refPreview" class="ref-preview" hidden></div>
|
||||
<div id="filePreview" class="file-preview" hidden></div>
|
||||
<div class="input-area">
|
||||
<input type="file" id="fileInput" accept="image/jpeg,image/png,image/gif,image/webp,application/pdf" multiple hidden>
|
||||
|
||||
+61
-4
@@ -3,6 +3,7 @@
|
||||
const messages = [];
|
||||
let isStreaming = false;
|
||||
let pendingFiles = []; // [{ name, type, base64 }]
|
||||
let pendingRefs = []; // [{ path, from, to }] - Workspace-Dateireferenzen
|
||||
|
||||
async function clearChat() {
|
||||
const archive = await apiArchive(getCurrentSessionId());
|
||||
@@ -23,12 +24,23 @@ async function sendMessage() {
|
||||
const input = $('#input');
|
||||
const btn = $('#send');
|
||||
const text = input.value.trim();
|
||||
if (!text && pendingFiles.length === 0) return;
|
||||
if (!text && pendingFiles.length === 0 && pendingRefs.length === 0) return;
|
||||
|
||||
// Content bauen: string oder array mit file-blocks
|
||||
let content;
|
||||
let bubbleText = text;
|
||||
|
||||
// Refs in den Text einbauen
|
||||
let msgText = text;
|
||||
if (pendingRefs.length > 0) {
|
||||
const refTags = pendingRefs.map(r => {
|
||||
if (r.from && r.to) return `[Datei: ${r.path}:${r.from}-${r.to}]`;
|
||||
return `[Datei: ${r.path}]`;
|
||||
});
|
||||
msgText = refTags.join('\n') + (text ? '\n' + text : '');
|
||||
clearPendingRefs();
|
||||
}
|
||||
|
||||
if (pendingFiles.length > 0) {
|
||||
content = [];
|
||||
const labels = [];
|
||||
@@ -41,11 +53,12 @@ async function sendMessage() {
|
||||
});
|
||||
labels.push((blockType === 'image' ? '📷 ' : '📄 ') + f.name);
|
||||
}
|
||||
if (text) content.push({ type: 'text', text });
|
||||
bubbleText = labels.join('\n') + (text ? '\n' + text : '');
|
||||
if (msgText) content.push({ type: 'text', text: msgText });
|
||||
bubbleText = labels.join('\n') + (msgText ? '\n' + msgText : '');
|
||||
clearPendingFiles();
|
||||
} else {
|
||||
content = text;
|
||||
content = msgText;
|
||||
bubbleText = msgText;
|
||||
}
|
||||
|
||||
messages.push({ role: 'user', content });
|
||||
@@ -197,6 +210,50 @@ function removePendingFile(index) {
|
||||
renderFilePreview();
|
||||
}
|
||||
|
||||
// ── Workspace Refs ──
|
||||
|
||||
function addPendingRef(ref) {
|
||||
// ref = "path" oder "path:from-to"
|
||||
const match = ref.match(/^(.+?):(\d+)-(\d+)$/);
|
||||
if (match) {
|
||||
pendingRefs.push({ path: match[1], from: parseInt(match[2]), to: parseInt(match[3]) });
|
||||
} else {
|
||||
pendingRefs.push({ path: ref, from: null, to: null });
|
||||
}
|
||||
renderRefPreview();
|
||||
}
|
||||
|
||||
function removePendingRef(index) {
|
||||
pendingRefs.splice(index, 1);
|
||||
renderRefPreview();
|
||||
}
|
||||
|
||||
function clearPendingRefs() {
|
||||
pendingRefs.length = 0;
|
||||
renderRefPreview();
|
||||
}
|
||||
|
||||
function renderRefPreview() {
|
||||
const container = $('#refPreview');
|
||||
if (!container) return;
|
||||
|
||||
if (pendingRefs.length === 0) {
|
||||
container.innerHTML = '';
|
||||
container.hidden = true;
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = pendingRefs.map((r, i) => {
|
||||
const label = r.from && r.to ? `${r.path}:${r.from}-${r.to}` : r.path;
|
||||
return `<div class="ref-preview-item">
|
||||
<span class="ref-icon">📂</span>
|
||||
<span class="ref-label">${esc(label)}</span>
|
||||
<button class="file-remove" onclick="removePendingRef(${i})">✕</button>
|
||||
</div>`;
|
||||
}).join('');
|
||||
container.hidden = false;
|
||||
}
|
||||
|
||||
function clearPendingFiles() {
|
||||
pendingFiles.length = 0;
|
||||
const preview = $('#filePreview');
|
||||
|
||||
@@ -50,12 +50,8 @@ registerPage('chat', {
|
||||
openFileExplorer({
|
||||
sessionId,
|
||||
onSelect(ref) {
|
||||
const input = document.getElementById('input');
|
||||
if (!input) return;
|
||||
const tag = `[Datei: ${ref}]`;
|
||||
const pos = input.selectionStart || input.value.length;
|
||||
input.value = input.value.substring(0, pos) + tag + input.value.substring(pos);
|
||||
input.focus();
|
||||
addPendingRef(ref);
|
||||
document.getElementById('input')?.focus();
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -117,5 +113,6 @@ registerPage('chat', {
|
||||
loadedArchiveCount = 0;
|
||||
isStreaming = false;
|
||||
clearPendingFiles();
|
||||
clearPendingRefs();
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user