diff --git a/src/popup/styles/main.css b/src/popup/styles/main.css index 851dcc8..6a0311b 100644 --- a/src/popup/styles/main.css +++ b/src/popup/styles/main.css @@ -15,6 +15,21 @@ --color-section: #dddddd; } +@keyframes copy-flash { + 0% { + background-color: var(--color-fg); + color: var(--color-bg); + } + 100% { + background-color: transparent; + color: inherit; + } +} + +.copy-flash { + animation: copy-flash 500ms ease-out; +} + body { width: 396px; overflow-x: hidden; diff --git a/src/popup/views/addressDetail.js b/src/popup/views/addressDetail.js index 2deb222..f986cab 100644 --- a/src/popup/views/addressDetail.js +++ b/src/popup/views/addressDetail.js @@ -2,6 +2,7 @@ const { $, showView, showFlash, + flashCopyElement, balanceLinesForAddress, addressDotHtml, addressTitle, @@ -237,9 +238,11 @@ function renderTransactions(txs) { function init(_ctx) { ctx = _ctx; $("address-full").addEventListener("click", () => { - const addr = $("address-full").dataset.full; + const el = $("address-full"); + const addr = el.dataset.full; if (addr) { navigator.clipboard.writeText(addr); + flashCopyElement(el); showFlash("Copied!"); } }); @@ -354,17 +357,21 @@ function init(_ctx) { }); $("export-privkey-value").addEventListener("click", () => { - const key = $("export-privkey-value").textContent; + const el = $("export-privkey-value"); + const key = el.textContent; if (key) { navigator.clipboard.writeText(key); + flashCopyElement(el); showFlash("Copied!"); } }); $("export-privkey-address").addEventListener("click", () => { - const full = $("export-privkey-address").dataset.full; + const el = $("export-privkey-address"); + const full = el.dataset.full; if (full) { navigator.clipboard.writeText(full); + flashCopyElement(el); showFlash("Copied!"); } }); diff --git a/src/popup/views/addressToken.js b/src/popup/views/addressToken.js index 72c95c0..fd8263e 100644 --- a/src/popup/views/addressToken.js +++ b/src/popup/views/addressToken.js @@ -5,6 +5,7 @@ const { $, showView, showFlash, + flashCopyElement, addressDotHtml, addressTitle, escapeHtml, @@ -313,9 +314,11 @@ function renderTransactions(txs) { function init(_ctx) { ctx = _ctx; $("address-token-full").addEventListener("click", () => { - const addr = $("address-token-full").dataset.full; + const el = $("address-token-full"); + const addr = el.dataset.full; if (addr) { navigator.clipboard.writeText(addr); + flashCopyElement(el); showFlash("Copied!"); } }); @@ -324,6 +327,7 @@ function init(_ctx) { const copyEl = e.target.closest("[data-copy]"); if (copyEl) { navigator.clipboard.writeText(copyEl.dataset.copy); + flashCopyElement(copyEl); showFlash("Copied!"); } }); @@ -372,6 +376,7 @@ function init(_ctx) { if (copyEl) { copyEl.addEventListener("click", () => { navigator.clipboard.writeText(copyEl.dataset.copy); + flashCopyElement(copyEl); showFlash("Copied!"); }); } diff --git a/src/popup/views/confirmTx.js b/src/popup/views/confirmTx.js index 522e9e5..fe5f45e 100644 --- a/src/popup/views/confirmTx.js +++ b/src/popup/views/confirmTx.js @@ -15,6 +15,7 @@ const { hideError, showView, showFlash, + flashCopyElement, addressTitle, addressDotHtml, escapeHtml, @@ -116,6 +117,7 @@ function show(txInfo) { if (copyEl) { copyEl.onclick = () => { navigator.clipboard.writeText(copyEl.dataset.copy); + flashCopyElement(copyEl); showFlash("Copied!"); }; } diff --git a/src/popup/views/helpers.js b/src/popup/views/helpers.js index 8fdfe65..42e293d 100644 --- a/src/popup/views/helpers.js +++ b/src/popup/views/helpers.js @@ -76,6 +76,18 @@ function clearFlash() { $("flash-msg").textContent = ""; } +function flashCopyElement(el) { + el.classList.remove("copy-flash"); + // Force reflow so re-adding the class restarts the animation. + void el.offsetWidth; + el.classList.add("copy-flash"); + el.addEventListener( + "animationend", + () => el.classList.remove("copy-flash"), + { once: true }, + ); +} + function showFlash(msg, duration = 2000) { clearFlash(); $("flash-msg").textContent = msg; @@ -265,6 +277,7 @@ module.exports = { hideError, showView, showFlash, + flashCopyElement, balanceLine, balanceLinesForAddress, addressColor, diff --git a/src/popup/views/home.js b/src/popup/views/home.js index ea923e0..43fc88c 100644 --- a/src/popup/views/home.js +++ b/src/popup/views/home.js @@ -2,6 +2,7 @@ const { $, showView, showFlash, + flashCopyElement, balanceLinesForAddress, isoDate, timeAgo, @@ -85,8 +86,9 @@ function renderActiveAddress() { el.innerHTML = `${dot}${escapeHtml(addr)}` + `${EXT_ICON}`; - $("active-addr-copy").addEventListener("click", () => { + $("active-addr-copy").addEventListener("click", (e) => { navigator.clipboard.writeText(addr); + flashCopyElement(e.currentTarget); showFlash("Copied!"); }); } else { diff --git a/src/popup/views/receive.js b/src/popup/views/receive.js index 1c2403f..ff9d646 100644 --- a/src/popup/views/receive.js +++ b/src/popup/views/receive.js @@ -2,6 +2,7 @@ const { $, showView, showFlash, + flashCopyElement, formatAddressHtml, addressTitle, } = require("./helpers"); @@ -61,17 +62,21 @@ function show() { function init(ctx) { $("receive-address-block").addEventListener("click", () => { - const addr = $("receive-address-block").dataset.full; + const el = $("receive-address-block"); + const addr = el.dataset.full; if (addr) { navigator.clipboard.writeText(addr); + flashCopyElement(el); showFlash("Copied!"); } }); $("btn-receive-copy").addEventListener("click", () => { - const addr = $("receive-address-block").dataset.full; + const block = $("receive-address-block"); + const addr = block.dataset.full; if (addr) { navigator.clipboard.writeText(addr); + flashCopyElement(block); showFlash("Copied!"); } }); diff --git a/src/popup/views/transactionDetail.js b/src/popup/views/transactionDetail.js index bbfb0d9..b209efb 100644 --- a/src/popup/views/transactionDetail.js +++ b/src/popup/views/transactionDetail.js @@ -5,6 +5,7 @@ const { $, showView, showFlash, + flashCopyElement, addressDotHtml, addressTitle, escapeHtml, @@ -170,6 +171,7 @@ function render() { .forEach((el) => { el.onclick = () => { navigator.clipboard.writeText(el.dataset.copy); + flashCopyElement(el); showFlash("Copied!"); }; }); @@ -247,6 +249,7 @@ async function loadCalldata(txHash, toAddress) { container.querySelectorAll("[data-copy]").forEach((el) => { el.onclick = () => { navigator.clipboard.writeText(el.dataset.copy); + flashCopyElement(el); showFlash("Copied!"); }; }); diff --git a/src/popup/views/txStatus.js b/src/popup/views/txStatus.js index 66edb5d..6e2b77c 100644 --- a/src/popup/views/txStatus.js +++ b/src/popup/views/txStatus.js @@ -4,6 +4,7 @@ const { $, showView, showFlash, + flashCopyElement, addressDotHtml, addressTitle, escapeHtml, @@ -76,6 +77,7 @@ function attachCopyHandlers(viewId) { .forEach((el) => { el.onclick = () => { navigator.clipboard.writeText(el.dataset.copy); + flashCopyElement(el); showFlash("Copied!"); }; });