Hide PDF download button in user messages

사용자가 업로드한 PDF는 이미 갖고 있으므로 저장 버튼 불필요.
renderMarkdown/renderLinkButton에 hideDownload 옵션 추가,
유저 메시지 렌더링 시 적용. 미리보기 버튼은 유지.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
kim
2026-05-19 12:27:39 +09:00
co-authored by Claude Sonnet 4.6
parent d1423c9a3b
commit e2c6395a9a
+7 -6
View File
@@ -4735,7 +4735,7 @@ function renderChatMessages() {
<div class="msg-avatar">${msg.role === 'user' ? 'U' : '<img src="cherry_logo.png" style="width:48px;height:48px;border-radius:6px">'}</div> <div class="msg-avatar">${msg.role === 'user' ? 'U' : '<img src="cherry_logo.png" style="width:48px;height:48px;border-radius:6px">'}</div>
<div class="msg-body"> <div class="msg-body">
<div class="msg-role">${msg.role === 'user' ? 'You' : (msg.mode === 'agentic' ? 'CherryClaw (Agent)' : 'CherryClaw')}</div> <div class="msg-role">${msg.role === 'user' ? 'You' : (msg.mode === 'agentic' ? 'CherryClaw (Agent)' : 'CherryClaw')}</div>
${msg.role === 'ai' ? renderAssistantContent(msg.content) : `<div class="msg-content">${renderMarkdown(msg.display !== undefined ? msg.display : msg.content)}</div>`} ${msg.role === 'ai' ? renderAssistantContent(msg.content) : `<div class="msg-content">${renderMarkdown(msg.display !== undefined ? msg.display : msg.content, { hideDownload: true })}</div>`}
${msg.role === 'ai' ? renderArtifacts(msg.artifacts) : ''} ${msg.role === 'ai' ? renderArtifacts(msg.artifacts) : ''}
${msg.role === 'ai' ? renderFileDownloads(msg.steps, msg.processEntries, msg.content) : ''} ${msg.role === 'ai' ? renderFileDownloads(msg.steps, msg.processEntries, msg.content) : ''}
${msg.role === 'ai' && msg.processEntries && msg.processEntries.length ? renderProcessPill(msg.processEntries) : ''} ${msg.role === 'ai' && msg.processEntries && msg.processEntries.length ? renderProcessPill(msg.processEntries) : ''}
@@ -8498,7 +8498,8 @@ function _normalizeFileUrl(url) {
return url; return url;
} }
function _renderLinkButton(text, url) { function _renderLinkButton(text, url, opts) {
var hideDownload = opts && opts.hideDownload;
url = _normalizeFileUrl(url); url = _normalizeFileUrl(url);
var fileExts = ['.pptx','.pdf','.xlsx','.xls','.docx','.doc','.zip','.csv','.mp4','.mp3']; var fileExts = ['.pptx','.pdf','.xlsx','.xls','.docx','.doc','.zip','.csv','.mp4','.mp3'];
var isDownload = fileExts.some(function(ext) { return text.toLowerCase().endsWith(ext); }) var isDownload = fileExts.some(function(ext) { return text.toLowerCase().endsWith(ext); })
@@ -8523,7 +8524,7 @@ function _renderLinkButton(text, url) {
+ '<a href="' + url + '" target="_blank" rel="noopener" class="download-btn" title="새 탭에서 열기">' + '<a href="' + url + '" target="_blank" rel="noopener" class="download-btn" title="새 탭에서 열기">'
+ '<span style="font-size:14px">📄</span> ' + text + '</a>' + '<span style="font-size:14px">📄</span> ' + text + '</a>'
+ '<button class="pptx-preview-btn" onclick="togglePdfEmbed(\'' + escHtml(url) + '\',\'' + pdfId + '\',this)">&#9664; 미리보기</button>' + '<button class="pptx-preview-btn" onclick="togglePdfEmbed(\'' + escHtml(url) + '\',\'' + pdfId + '\',this)">&#9664; 미리보기</button>'
+ '<a href="' + url + '" onclick="downloadFile(event,this)" class="pptx-preview-btn" style="text-decoration:none">&#11015; 저장</a>' + (hideDownload ? '' : '<a href="' + url + '" onclick="downloadFile(event,this)" class="pptx-preview-btn" style="text-decoration:none">&#11015; 저장</a>')
+ '</div>' + '</div>'
+ '<div id="' + pdfId + '" style="display:none">' + '<div id="' + pdfId + '" style="display:none">'
+ '<iframe style="width:100%;height:600px;border:1px solid var(--line);border-radius:8px" allowfullscreen></iframe>' + '<iframe style="width:100%;height:600px;border:1px solid var(--line);border-radius:8px" allowfullscreen></iframe>'
@@ -8661,7 +8662,7 @@ function toggleTxtEmbedBtn(btn) {
} }
} }
function renderMarkdown(text) { function renderMarkdown(text, opts) {
if (!text) return ''; if (!text) return '';
// Extract existing <img> tags before escaping so they survive escHtml() // Extract existing <img> tags before escaping so they survive escHtml()
@@ -8695,12 +8696,12 @@ function renderMarkdown(text) {
// Links: [text](url) — render download links for file types as buttons, PPTX gets preview // Links: [text](url) — render download links for file types as buttons, PPTX gets preview
html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, function(_, text, url) { html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, function(_, text, url) {
return _renderLinkButton(text, url); return _renderLinkButton(text, url, opts);
}); });
// Bare /api/files/... URLs — auto-convert to download buttons even without markdown syntax // Bare /api/files/... URLs — auto-convert to download buttons even without markdown syntax
html = html.replace(/(\s|^)(\/api\/files\/[^\s<"]+)/g, function(_, space, url) { html = html.replace(/(\s|^)(\/api\/files\/[^\s<"]+)/g, function(_, space, url) {
return space + _renderLinkButton(decodeURIComponent(url.split('/').pop() || 'download'), url); return space + _renderLinkButton(decodeURIComponent(url.split('/').pop() || 'download'), url, opts);
}); });
// Bold // Bold