diff --git a/src/popup/styles/main.css b/src/popup/styles/main.css index 851dcc8..2b04e76 100644 --- a/src/popup/styles/main.css +++ b/src/popup/styles/main.css @@ -19,3 +19,16 @@ body { width: 396px; overflow-x: hidden; } + +/* Copy-flash feedback: inverts colors then fades back */ +.copy-flash-active { + background-color: var(--color-fg) !important; + color: var(--color-bg) !important; + transition: none; +} + +.copy-flash-fade { + transition: + background-color 300ms ease-out, + color 300ms ease-out; +} diff --git a/src/popup/views/addressDetail.js b/src/popup/views/addressDetail.js index 2deb222..fd28e96 100644 --- a/src/popup/views/addressDetail.js +++ b/src/popup/views/addressDetail.js @@ -2,6 +2,7 @@ const { $, showView, showFlash, + flashCopyFeedback, balanceLinesForAddress, addressDotHtml, addressTitle, @@ -241,6 +242,7 @@ function init(_ctx) { if (addr) { navigator.clipboard.writeText(addr); showFlash("Copied!"); + flashCopyFeedback($("address-full")); } }); @@ -358,6 +360,7 @@ function init(_ctx) { if (key) { navigator.clipboard.writeText(key); showFlash("Copied!"); + flashCopyFeedback($("export-privkey-value")); } }); @@ -366,6 +369,7 @@ function init(_ctx) { if (full) { navigator.clipboard.writeText(full); showFlash("Copied!"); + flashCopyFeedback($("export-privkey-address")); } }); diff --git a/src/popup/views/addressToken.js b/src/popup/views/addressToken.js index 72c95c0..b0e926b 100644 --- a/src/popup/views/addressToken.js +++ b/src/popup/views/addressToken.js @@ -5,6 +5,7 @@ const { $, showView, showFlash, + flashCopyFeedback, addressDotHtml, addressTitle, escapeHtml, @@ -317,6 +318,7 @@ function init(_ctx) { if (addr) { navigator.clipboard.writeText(addr); showFlash("Copied!"); + flashCopyFeedback($("address-token-full")); } }); @@ -325,6 +327,7 @@ function init(_ctx) { if (copyEl) { navigator.clipboard.writeText(copyEl.dataset.copy); showFlash("Copied!"); + flashCopyFeedback(copyEl); } }); @@ -373,6 +376,7 @@ function init(_ctx) { copyEl.addEventListener("click", () => { navigator.clipboard.writeText(copyEl.dataset.copy); showFlash("Copied!"); + flashCopyFeedback(copyEl); }); } updateSendBalance(); diff --git a/src/popup/views/confirmTx.js b/src/popup/views/confirmTx.js index c71475b..a2b30eb 100644 --- a/src/popup/views/confirmTx.js +++ b/src/popup/views/confirmTx.js @@ -15,6 +15,7 @@ const { hideError, showView, showFlash, + flashCopyFeedback, addressTitle, addressDotHtml, escapeHtml, @@ -117,6 +118,7 @@ function show(txInfo) { copyEl.onclick = () => { navigator.clipboard.writeText(copyEl.dataset.copy); showFlash("Copied!"); + flashCopyFeedback(copyEl); }; } } else { diff --git a/src/popup/views/helpers.js b/src/popup/views/helpers.js index 2db8191..45329ea 100644 --- a/src/popup/views/helpers.js +++ b/src/popup/views/helpers.js @@ -258,12 +258,26 @@ function timeAgo(timestamp) { return years + " year" + (years !== 1 ? "s" : "") + " ago"; } +function flashCopyFeedback(el) { + if (!el) return; + el.classList.remove("copy-flash-fade"); + el.classList.add("copy-flash-active"); + setTimeout(() => { + el.classList.remove("copy-flash-active"); + el.classList.add("copy-flash-fade"); + setTimeout(() => { + el.classList.remove("copy-flash-fade"); + }, 350); + }, 100); +} + module.exports = { $, showError, hideError, showView, showFlash, + flashCopyFeedback, balanceLine, balanceLinesForAddress, addressColor, diff --git a/src/popup/views/home.js b/src/popup/views/home.js index 68237e8..d6c2f73 100644 --- a/src/popup/views/home.js +++ b/src/popup/views/home.js @@ -2,6 +2,7 @@ const { $, showView, showFlash, + flashCopyFeedback, balanceLinesForAddress, isoDate, timeAgo, @@ -85,9 +86,10 @@ function renderActiveAddress() { el.innerHTML = `${dot}${escapeHtml(addr)}` + `${EXT_ICON}`; - $("active-addr-copy").addEventListener("click", () => { + $("active-addr-copy").addEventListener("click", (e) => { navigator.clipboard.writeText(addr); showFlash("Copied!"); + flashCopyFeedback(e.currentTarget); }); } else { el.textContent = ""; diff --git a/src/popup/views/receive.js b/src/popup/views/receive.js index 1c2403f..0169f18 100644 --- a/src/popup/views/receive.js +++ b/src/popup/views/receive.js @@ -2,6 +2,7 @@ const { $, showView, showFlash, + flashCopyFeedback, formatAddressHtml, addressTitle, } = require("./helpers"); @@ -60,11 +61,12 @@ function show() { } function init(ctx) { - $("receive-address-block").addEventListener("click", () => { + $("receive-address-block").addEventListener("click", (e) => { const addr = $("receive-address-block").dataset.full; if (addr) { navigator.clipboard.writeText(addr); showFlash("Copied!"); + flashCopyFeedback(e.currentTarget); } }); @@ -73,6 +75,7 @@ function init(ctx) { if (addr) { navigator.clipboard.writeText(addr); showFlash("Copied!"); + flashCopyFeedback($("receive-address-block")); } }); diff --git a/src/popup/views/transactionDetail.js b/src/popup/views/transactionDetail.js index bbfb0d9..e8cb1d5 100644 --- a/src/popup/views/transactionDetail.js +++ b/src/popup/views/transactionDetail.js @@ -5,6 +5,7 @@ const { $, showView, showFlash, + flashCopyFeedback, addressDotHtml, addressTitle, escapeHtml, @@ -171,6 +172,7 @@ function render() { el.onclick = () => { navigator.clipboard.writeText(el.dataset.copy); showFlash("Copied!"); + flashCopyFeedback(el); }; }); } @@ -248,6 +250,7 @@ async function loadCalldata(txHash, toAddress) { el.onclick = () => { navigator.clipboard.writeText(el.dataset.copy); showFlash("Copied!"); + flashCopyFeedback(el); }; }); } diff --git a/src/popup/views/txStatus.js b/src/popup/views/txStatus.js index 66edb5d..a406dca 100644 --- a/src/popup/views/txStatus.js +++ b/src/popup/views/txStatus.js @@ -4,6 +4,7 @@ const { $, showView, showFlash, + flashCopyFeedback, addressDotHtml, addressTitle, escapeHtml, @@ -77,6 +78,7 @@ function attachCopyHandlers(viewId) { el.onclick = () => { navigator.clipboard.writeText(el.dataset.copy); showFlash("Copied!"); + flashCopyFeedback(el); }; }); }