add clickable links, media embeds and lightbox to chat
- URLs are now clickable (open in new tab) - Images (jpg/png/gif/webp/svg) embed inline, click for fullscreen - Videos (mp4/webm) embed inline with controls, click for fullscreen - PDFs and other files open in new tab (browser handles download) - Fullscreen lightbox closes on click or Escape Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
a58b5073c6
commit
5b91975061
|
|
@ -64,11 +64,19 @@
|
|||
|
||||
.chat-box { background: #080810; border: 1px solid #1E1E2E; border-radius: 6px;
|
||||
min-height: 120px; max-height: 250px; overflow-y: auto; padding: 8px; margin-bottom: 8px; }
|
||||
.chat-msg { margin-bottom: 6px; padding: 6px 10px; border-radius: 6px; font-size: 13px; }
|
||||
.chat-msg { margin-bottom: 6px; padding: 6px 10px; border-radius: 6px; font-size: 13px; line-height: 1.5; word-wrap: break-word; }
|
||||
.chat-msg.sent { background: #0096FF; color: #fff; margin-left: 20%; text-align: right; }
|
||||
.chat-msg.received { background: #1E1E2E; margin-right: 20%; }
|
||||
.chat-msg.error { background: #3B1010; color: #FF6B6B; }
|
||||
.chat-msg .meta { font-size: 10px; color: rgba(255,255,255,0.4); margin-top: 2px; }
|
||||
.chat-msg a { color: #66BBFF; text-decoration: underline; }
|
||||
.chat-msg.sent a { color: #CCEEFF; }
|
||||
.chat-msg .chat-media { max-width: 100%; max-height: 200px; border-radius: 4px; margin-top: 4px; cursor: pointer; display: block; }
|
||||
.chat-msg .chat-media:hover { opacity: 0.85; }
|
||||
.lightbox-overlay { display:none; position:fixed; top:0; left:0; right:0; bottom:0; background:rgba(0,0,0,0.92);
|
||||
z-index:2000; justify-content:center; align-items:center; cursor:pointer; }
|
||||
.lightbox-overlay.open { display:flex; }
|
||||
.lightbox-overlay img, .lightbox-overlay video { max-width:95vw; max-height:95vh; border-radius:8px; }
|
||||
|
||||
.input-row { display: flex; gap: 6px; }
|
||||
.input-row input { flex: 1; background: #1E1E2E; border: 1px solid #333; border-radius: 6px;
|
||||
|
|
@ -368,6 +376,9 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Lightbox fuer Medien -->
|
||||
<div class="lightbox-overlay" id="lightbox" onclick="closeLightbox()"></div>
|
||||
|
||||
<script>
|
||||
const chatBox = document.getElementById('chat-box');
|
||||
const pauseHint = document.getElementById('pause-hint');
|
||||
|
|
@ -803,14 +814,51 @@
|
|||
if (autoScroll[tab]) box.scrollTop = box.scrollHeight;
|
||||
}
|
||||
|
||||
const MEDIA_IMG = /\.(jpe?g|png|gif|webp|svg|bmp|ico)$/i;
|
||||
const MEDIA_VID = /\.(mp4|webm|ogg|mov)$/i;
|
||||
const FILE_PDF = /\.pdf$/i;
|
||||
|
||||
function linkifyText(escaped) {
|
||||
// URLs in escaped HTML erkennen und ersetzen
|
||||
return escaped.replace(/(https?:\/\/[^\s<&]+)/g, function(url) {
|
||||
const decoded = url.replace(/&/g, '&');
|
||||
const pathname = new URL(decoded).pathname;
|
||||
if (MEDIA_IMG.test(pathname)) {
|
||||
return `<a href="${url}" target="_blank">${url}</a><img src="${url}" class="chat-media" onclick="event.stopPropagation();openLightbox('img','${url}')">`;
|
||||
}
|
||||
if (MEDIA_VID.test(pathname)) {
|
||||
return `<a href="${url}" target="_blank">${url}</a><video src="${url}" class="chat-media" controls onclick="event.stopPropagation();openLightbox('video','${url}')"></video>`;
|
||||
}
|
||||
return `<a href="${url}" target="_blank" rel="noopener">${url}</a>`;
|
||||
});
|
||||
}
|
||||
|
||||
function addChat(type, text, meta) {
|
||||
const el = document.createElement('div');
|
||||
el.className = `chat-msg ${type}`;
|
||||
el.innerHTML = `${escapeHtml(text)}<div class="meta">${escapeHtml(meta)} — ${new Date().toLocaleTimeString('de-DE')}</div>`;
|
||||
const escaped = escapeHtml(text);
|
||||
const linked = linkifyText(escaped);
|
||||
el.innerHTML = `${linked}<div class="meta">${escapeHtml(meta)} — ${new Date().toLocaleTimeString('de-DE')}</div>`;
|
||||
chatBox.appendChild(el);
|
||||
chatBox.scrollTop = chatBox.scrollHeight;
|
||||
}
|
||||
|
||||
function openLightbox(mediaType, url) {
|
||||
const lb = document.getElementById('lightbox');
|
||||
if (mediaType === 'video') {
|
||||
lb.innerHTML = `<video src="${url}" controls autoplay style="max-width:95vw;max-height:95vh;border-radius:8px;" onclick="event.stopPropagation()"></video>`;
|
||||
} else {
|
||||
lb.innerHTML = `<img src="${url}" style="max-width:95vw;max-height:95vh;border-radius:8px;">`;
|
||||
}
|
||||
lb.classList.add('open');
|
||||
}
|
||||
|
||||
function closeLightbox() {
|
||||
const lb = document.getElementById('lightbox');
|
||||
lb.classList.remove('open');
|
||||
lb.innerHTML = '';
|
||||
}
|
||||
|
||||
function showDockerLogs(msg) {
|
||||
const tab = msg.tab;
|
||||
const box = logBoxes[tab];
|
||||
|
|
@ -867,6 +915,11 @@
|
|||
if (e.key === 'Enter') testGateway();
|
||||
});
|
||||
|
||||
// Escape schliesst Lightbox
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape') closeLightbox();
|
||||
});
|
||||
|
||||
// ── ARIA Live-Ansicht (SSH + Desktop) ──────────────────
|
||||
|
||||
let liveSshTerm = null;
|
||||
|
|
|
|||
Loading…
Reference in New Issue