fix(comment-cards): 복사 버튼 제거, 카드 클릭으로 복사

복사 버튼이 캡처 이미지에 함께 찍히던 문제 해결. 버튼을 없애고 카드 자체 클릭으로
복사하도록 변경, 완료 피드백은 카드 밖 토스트로 표시(캡처에 미포함). JS 캐시버스터 갱신.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
hehihoho3@gmail.com 2026-06-29 18:31:25 +09:00
parent ee5a13163b
commit 7de8f954ad
2 changed files with 34 additions and 16 deletions

View File

@ -63,13 +63,11 @@
head.querySelector('.cc-time').textContent = timeAgo(c.publishedAt);
head.querySelector('.cc-text').textContent = toPlainText(c.text);
const copyBtn = document.createElement('button');
copyBtn.className = 'cc-btn secondary cc-copy';
copyBtn.textContent = '복사';
copyBtn.addEventListener('click', () => window.copyCard(card, copyBtn)); // Task 5에서 정의
// 카드 자체를 클릭하면 복사 (버튼이 캡처 이미지에 찍히지 않도록 버튼 제거)
card.title = '클릭하면 이미지 복사';
card.addEventListener('click', () => window.copyCard(card));
card.appendChild(head);
card.appendChild(copyBtn);
grid.appendChild(card);
});
if (window.lucide) window.lucide.createIcons();
@ -91,29 +89,44 @@
URL.revokeObjectURL(a.href);
}
window.copyCard = async function (cardEl, btnEl) {
const original = btnEl.textContent;
btnEl.disabled = true; btnEl.textContent = '복사 중…';
let toastTimer = null;
function showToast(msg) {
let t = document.getElementById('ccToast');
if (!t) {
t = document.createElement('div');
t.id = 'ccToast';
t.className = 'cc-toast';
document.body.appendChild(t);
}
t.textContent = msg;
t.classList.add('show');
if (toastTimer) clearTimeout(toastTimer);
toastTimer = setTimeout(() => t.classList.remove('show'), 1500);
}
window.copyCard = async function (cardEl) {
if (cardEl.dataset.copying === '1') return; // 중복 클릭 방지
cardEl.dataset.copying = '1';
try {
const blob = await captureBlob(cardEl);
if (navigator.clipboard && window.ClipboardItem) {
await navigator.clipboard.write([new ClipboardItem({ 'image/png': blob })]);
btnEl.textContent = '복사됨 ✓';
showToast('복사됨 ✓');
} else {
downloadBlob(blob);
btnEl.textContent = '다운로드됨';
showToast('다운로드됨');
}
} catch (e) {
// 클립보드 권한 거부 등 → 다운로드 폴백
try {
const blob = await captureBlob(cardEl);
downloadBlob(blob);
btnEl.textContent = '다운로드됨';
showToast('다운로드됨');
} catch (e2) {
btnEl.textContent = '실패';
showToast('복사 실패');
}
} finally {
setTimeout(() => { btnEl.disabled = false; btnEl.textContent = original; }, 1500);
setTimeout(() => { delete cardEl.dataset.copying; }, 600);
}
};

View File

@ -26,7 +26,12 @@
.cc-time { font-size:11.5px; color:var(--text-3); margin-left:.4rem; }
.cc-text { font-size:14px; color:var(--text); margin-top:.35rem; white-space:pre-wrap; word-break:break-word; line-height:1.45; }
.cc-stats { font-size:12px; color:var(--text-3); margin-top:.5rem; display:flex; gap:1rem; }
.cc-copy { position:absolute; top:.6rem; right:.6rem; }
.comment-card { cursor:pointer; }
/* 복사 완료 토스트 — 카드 밖(body)에 떠서 캡처 이미지에 안 찍힘 */
.cc-toast { position:fixed; left:50%; bottom:2rem; transform:translateX(-50%) translateY(1rem);
background:var(--text); color:var(--surface); padding:.6rem 1.1rem; border-radius:999px;
font-size:14px; font-weight:600; opacity:0; pointer-events:none; transition:opacity .15s, transform .15s; z-index:9999; }
.cc-toast.show { opacity:1; transform:translateX(-50%) translateY(0); }
/* 모자이크 */
.comment-card.mosaic .cc-avatar { filter: blur(6px); }
.comment-card.mosaic .cc-author { filter: blur(5px); }
@ -37,7 +42,7 @@
<div layout:fragment="content">
<h1 style="font-size:1.5rem;font-weight:700;margin-bottom:.3rem;">댓글 카드</h1>
<p style="color:var(--text-3);margin-bottom:1.2rem;font-size:14px;">
유튜브 링크의 댓글을 가져와 카드로 만들고, 프로필·아이디를 모자이크해 영상 소스로 복사하세요.
유튜브 링크의 댓글을 가져와 카드로 만들고, 프로필·아이디를 모자이크하세요. <b>카드를 클릭하면 이미지가 복사</b>됩니다(캡컷 등에 Ctrl+V).
</p>
<div class="cc-toolbar">
@ -66,7 +71,7 @@
<th:block layout:fragment="script">
<!-- DOM→이미지 캡처 (Task 5에서 사용). blur 필터 지원 위해 modern-screenshot 사용. -->
<script src="https://cdn.jsdelivr.net/npm/modern-screenshot@4/dist/index.js"></script>
<script th:src="@{/js/comment-cards.js(v=20260629b)}"></script>
<script th:src="@{/js/comment-cards.js(v=20260629c)}"></script>
</th:block>
</body>
</html>