From 47d7b7ba021ddb99ddc96e3b48aeb19096d41f39 Mon Sep 17 00:00:00 2001 From: Mike Conrad Date: Sun, 27 Aug 2023 20:26:25 -0400 Subject: [PATCH] Added toast and copy to clipboard functionality --- src/main.ts | 4 +++- src/style.css | 21 +++++++++++++++++++-- src/toast.ts | 14 ++++++++++++++ src/tokenList.ts | 4 +--- src/tokenListItem.test.ts | 2 +- src/tokenListItem.ts | 26 +++++++++++++++----------- src/utils/root.ts | 6 ++++++ 7 files changed, 59 insertions(+), 18 deletions(-) create mode 100644 src/toast.ts create mode 100644 src/utils/root.ts diff --git a/src/main.ts b/src/main.ts index 2d8e73f..fa52e6a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,8 @@ import "./style.css"; import { tokenList } from "./tokenList"; -document.querySelector("#app")!.innerHTML = ` +import rootDiv from "./utils/root"; + +rootDiv!.innerHTML = ` ${tokenList()} `; diff --git a/src/style.css b/src/style.css index 1970da4..8abc907 100644 --- a/src/style.css +++ b/src/style.css @@ -41,6 +41,10 @@ h1 { margin: 0 auto; padding: 2rem; text-align: center; + display: flex; + align-items: center; + justify-content: center; + flex-direction: column-reverse; } .card { @@ -81,14 +85,16 @@ button:focus-visible { .fieldset-wrapper, form { display: flex; flex: 1; + } form { flex-direction: column; } .fieldset-wrapper { - border: 1px solid; + border: 1px solid gainsboro; padding: 5px; - border-bottom: 1px solid; + border-radius: 4px; + box-shadow: 1px 0px 6px 2px gainsboro; } fieldset { @@ -111,4 +117,15 @@ label { display: flex; justify-content: center; align-items: center; + border: 1px solid; +} + +.toast { + background-color: lightseagreen; + padding: 10px; + position: relative; + top: 10px; + right: 10px; + color: white; + font-weight: bold; } \ No newline at end of file diff --git a/src/toast.ts b/src/toast.ts new file mode 100644 index 0000000..86e1815 --- /dev/null +++ b/src/toast.ts @@ -0,0 +1,14 @@ +export function toast(element: HTMLDivElement, message: string) { + // Target our predefined DIV that will hold toast messages. + const toastDiv = element.getElementsByClassName('toast') + + // If we currently have a toast displayed, let's remove it from the DOM. + if (toastDiv && toastDiv.length != 0) { + for (const el of toastDiv){ + el.remove() + } + } + + // Finally add our toast message. + element.innerHTML += `
${message}
` +} \ No newline at end of file diff --git a/src/tokenList.ts b/src/tokenList.ts index 9136b65..bf04376 100644 --- a/src/tokenList.ts +++ b/src/tokenList.ts @@ -2,9 +2,7 @@ import { displayTokenListItem } from "./TokenListItem"; import { tokens } from "./tokens"; export function tokenList() { - const element = document.createElement("div"); - element.classList.add("test"); return `
${tokens.map((token) => - displayTokenListItem(token.account, token.secret, element) + displayTokenListItem(token.account, token.secret) )}
`; } diff --git a/src/tokenListItem.test.ts b/src/tokenListItem.test.ts index 81e9184..0e3cbcd 100644 --- a/src/tokenListItem.test.ts +++ b/src/tokenListItem.test.ts @@ -5,7 +5,7 @@ import { displayTokenListItem } from "./tokenListItem"; test("displays correct account name", () => { const div: HTMLDivElement = document.createElement("div"); - displayTokenListItem("Github", "ABCDEFGHIJKLMNOP", div); + displayTokenListItem("Github", "ABCDEFGHIJKLMNOP"); expect(div.innerHTML).toContain("Github"); }); diff --git a/src/tokenListItem.ts b/src/tokenListItem.ts index e757b6c..1a17660 100644 --- a/src/tokenListItem.ts +++ b/src/tokenListItem.ts @@ -1,16 +1,15 @@ +import { toast } from "./toast"; import { displayToken } from "./token"; -var secondsSinceEpoch: number; -var secondsSinceStart: number; -var secondsRemaining: number; -secondsSinceStart = 0; -secondsRemaining = 30; -const period = 30; -var token; +import rootDiv from "./utils/root" +let secondsSinceEpoch: number; +let secondsSinceStart: number = 0; +let secondsRemaining: number = 30; +const period: 30 | 60 = 30; +let token: string; export function displayTokenListItem( account: string, secret: string, - element: HTMLDivElement ) { function countdown() { secondsSinceEpoch = Math.ceil(Date.now() / 1000) - 1; @@ -18,19 +17,24 @@ export function displayTokenListItem( secondsRemaining = period - (secondsSinceEpoch % period); const timerDiv = document.getElementById(`timer-${account}`); const tokenDiv = document.getElementById(`secret-${account}`); - if (timerDiv && tokenDiv) { + + if (timerDiv && tokenDiv && rootDiv) { timerDiv.innerHTML = secondsRemaining.toString(); timerDiv.style.background = `conic-gradient(transparent ${ (100 / 30) * secondsSinceStart - }%, ${secondsRemaining < 10 ? "salmon" : "gainsboro"} 0)`; + }%, ${secondsRemaining < 10 ? "salmon" : "lightgreen"} 0)`; token = displayToken(secret); tokenDiv.innerHTML = token; + tokenDiv.addEventListener("click", () => { + navigator.clipboard.writeText(tokenDiv.innerHTML); + toast(rootDiv!, `${tokenDiv.innerHTML} Copied successfully`) + }); } } setInterval(() => { countdown(); }, 1000); - return (element.innerHTML = `
+ return (`

${account}

diff --git a/src/utils/root.ts b/src/utils/root.ts new file mode 100644 index 0000000..36f7d06 --- /dev/null +++ b/src/utils/root.ts @@ -0,0 +1,6 @@ +const rootDiv = document.querySelector("#app") +if (!rootDiv) { + const rootDiv = document.createElement('div') + rootDiv.id = 'app' +} +export default rootDiv \ No newline at end of file