diff --git a/src/main/resources/static/js/comment-cards.js b/src/main/resources/static/js/comment-cards.js index 022f469..3f3b36d 100644 --- a/src/main/resources/static/js/comment-cards.js +++ b/src/main/resources/static/js/comment-cards.js @@ -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); } }; diff --git a/src/main/resources/templates/comment-cards.html b/src/main/resources/templates/comment-cards.html index da19ce8..bf34c1b 100644 --- a/src/main/resources/templates/comment-cards.html +++ b/src/main/resources/templates/comment-cards.html @@ -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 @@

댓글 카드

- 유튜브 링크의 댓글을 가져와 카드로 만들고, 프로필·아이디를 모자이크해 영상 소스로 복사하세요. + 유튜브 링크의 댓글을 가져와 카드로 만들고, 프로필·아이디를 모자이크하세요. 카드를 클릭하면 이미지가 복사됩니다(캡컷 등에 Ctrl+V).

@@ -66,7 +71,7 @@ - +