107 lines
3.8 KiB
JavaScript
107 lines
3.8 KiB
JavaScript
// ── Shared Message Page (öffentlich, kein Login nötig) ──
|
||
|
||
registerPage('shared', {
|
||
init: async (params) => {
|
||
const token = params.id;
|
||
const container = document.getElementById('sharedContent');
|
||
if (!token || !container) {
|
||
container.innerHTML = '<div class="shared-error"><i class="fa fa-times-circle"></i> Ungültiger Link</div>';
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const data = await apiGetShared(token);
|
||
container.innerHTML = '';
|
||
|
||
let messages = [];
|
||
|
||
if (data.messages && data.messages.length > 0) {
|
||
messages = data.messages;
|
||
} else if (data.message) {
|
||
messages = [data.message];
|
||
}
|
||
|
||
// Aufeinanderfolgende Assistant-Text-Messages mergen (wie im Chat)
|
||
messages = _mergeConsecutiveTexts(messages);
|
||
|
||
for (const msg of messages) {
|
||
const c = msg.content || '';
|
||
|
||
// Web-Search-Results als Tool-Box mit Sources rendern
|
||
if (msg.type === 'web_search_result') {
|
||
var wsSources = [];
|
||
try { wsSources = JSON.parse(c || '[]'); } catch(e) {}
|
||
if (wsSources.length === 0) continue;
|
||
const div = document.createElement('div');
|
||
div.className = 'tool-box';
|
||
div.dataset.toolName = 'web_search';
|
||
renderToolBoxContent(div, 'web_search', null, null, false, wsSources);
|
||
container.appendChild(div);
|
||
continue;
|
||
}
|
||
|
||
const isReview = c.startsWith('[Review:') || c.startsWith('[Review-Feedback') || c.startsWith('[Finalizer:');
|
||
const div = document.createElement('div');
|
||
if (isReview) {
|
||
div.className = 'msg review-bubble markdown' + (c.startsWith('[Finalizer:') ? ' finalizer-bubble' : '');
|
||
} else {
|
||
div.className = 'msg ' + (msg.role === 'user' ? 'user' : 'assistant') + ' markdown';
|
||
}
|
||
if (!isReview && msg.role === 'user') {
|
||
renderUserContent(div, msg.content);
|
||
} else {
|
||
div.innerHTML = renderMarkdown(c);
|
||
parseFluentEmojis(div);
|
||
wrapKreaGalleries(div);
|
||
}
|
||
container.appendChild(div);
|
||
}
|
||
|
||
// Timestamp anzeigen
|
||
if (data.createdAt) {
|
||
const meta = document.createElement('div');
|
||
meta.className = 'shared-meta';
|
||
const d = new Date(data.createdAt);
|
||
meta.innerHTML = '<i class="fa fa-clock-o"></i> Geteilt am ' + d.toLocaleDateString('de-DE') + ' um ' + d.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' });
|
||
container.appendChild(meta);
|
||
}
|
||
|
||
} catch (err) {
|
||
container.innerHTML = '<div class="shared-error"><i class="fa fa-times-circle"></i> ' + esc(err.message) + '</div>';
|
||
}
|
||
},
|
||
destroy: () => {}
|
||
});
|
||
|
||
function _mergeConsecutiveTexts(msgs) {
|
||
const result = [];
|
||
for (const msg of msgs) {
|
||
const c = msg.content || '';
|
||
// web_search_result und Review/Finalizer-Messages nicht mergen
|
||
if (msg.type === 'web_search_result') {
|
||
result.push(Object.assign({}, msg));
|
||
continue;
|
||
}
|
||
const isReview = c.startsWith('[Review:') || c.startsWith('[Review-Feedback') || c.startsWith('[Finalizer:');
|
||
if (msg.role === 'assistant' && !isReview && msg.type !== 'web_search_result') {
|
||
// Rückwärts suchen – web_search_result überspringen
|
||
let prev = null;
|
||
for (let i = result.length - 1; i >= 0; i--) {
|
||
if (result[i].type === 'web_search_result') continue;
|
||
prev = result[i];
|
||
break;
|
||
}
|
||
if (prev && prev.role === 'assistant'
|
||
&& !(prev.content || '').startsWith('[Review:')
|
||
&& !(prev.content || '').startsWith('[Finalizer:')
|
||
&& prev.iteration === msg.iteration) {
|
||
prev.content = (prev.content || '') + '\n\n' + c;
|
||
if (msg.createdAt) prev.createdAt = msg.createdAt;
|
||
continue;
|
||
}
|
||
}
|
||
result.push(Object.assign({}, msg));
|
||
}
|
||
return result;
|
||
}
|