first commit! 🎉
port "ari is learning!" assets to live go backend. some prep work for further developments for ari melody LIVE
This commit is contained in:
commit
6927d54cbd
12 changed files with 675 additions and 0 deletions
125
learning/public/cards.css
Normal file
125
learning/public/cards.css
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
:root {
|
||||
--bg-0: #e0e0e0;
|
||||
--on-bg-0: #303030;
|
||||
--on-bg-1: #606060;
|
||||
--on-bg-2: #808080;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg-0: #202020;
|
||||
--on-bg-0: #e0e0e0;
|
||||
--on-bg-1: #c0c0c0;
|
||||
--on-bg-2: #808080;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
|
||||
font-family: "Inter", "Arial", sans-serif;
|
||||
font-size: 32px;
|
||||
|
||||
color: var(--on-bg-0);
|
||||
background-color: var(--bg-0);
|
||||
|
||||
transition: color 1s, background-color 1s;
|
||||
}
|
||||
|
||||
#app {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.vignette {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-image: radial-gradient(transparent, black);
|
||||
opacity: .1;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
.title h1, .title h2 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.title h1 {
|
||||
font-size: 2em;
|
||||
margin-bottom: -.2em;
|
||||
}
|
||||
|
||||
.title h2 {
|
||||
font-size: 1.25em;
|
||||
color: var(--on-bg-2);
|
||||
animation: pulse .5s alternate ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
from { opacity: 1; }
|
||||
to { opacity: .5; }
|
||||
}
|
||||
|
||||
header {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
footer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
header,
|
||||
footer {
|
||||
width: calc(100vw - 2.8em);
|
||||
padding: 1em 1.4em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
|
||||
color: var(--on-bg-2);
|
||||
}
|
||||
|
||||
header h3,
|
||||
footer h3 {
|
||||
margin: 0;
|
||||
font-family: "Monaspace Argon", monospace;
|
||||
}
|
||||
|
||||
#time {
|
||||
font-family: "Monaspace Argon", monospace;
|
||||
}
|
||||
|
||||
#cover {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: var(--bg-0);
|
||||
transition: opacity 1s ease-out;
|
||||
}
|
||||
|
||||
#cover.hidden {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
51
learning/public/cards.js
Normal file
51
learning/public/cards.js
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
const timeEl = document.getElementById("time");
|
||||
const titleEl = document.getElementById("title");
|
||||
const coverEl = document.getElementById("cover");
|
||||
|
||||
function render() {
|
||||
const date = new Date();
|
||||
|
||||
const tick = (date.getMilliseconds() * 0.001 % 1.0 > 0.5) ? ":" : " ";
|
||||
|
||||
const hh = `${date.getUTCHours()}`.padStart(2, "0");
|
||||
const mm = `${date.getUTCMinutes()}`.padStart(2, "0");
|
||||
const ss = `${date.getUTCSeconds()}`.padStart(2, "0");
|
||||
timeEl.innerText = `${hh}${tick}${mm}${tick}${ss}`;
|
||||
|
||||
requestAnimationFrame(render);
|
||||
}
|
||||
|
||||
function ready() {
|
||||
coverEl.classList.add("hidden");
|
||||
|
||||
requestAnimationFrame(render);
|
||||
}
|
||||
|
||||
async function updateTitle() {
|
||||
if (!titleEl) {
|
||||
ready();
|
||||
return;
|
||||
}
|
||||
|
||||
const eventSource = new EventSource("/learning/sse");
|
||||
eventSource.addEventListener("open", () => {
|
||||
console.log("Connected.");
|
||||
|
||||
eventSource.addEventListener("title-update", event => {
|
||||
console.log(`title updated: \"${titleEl.innerText}\" -> \"${event.data}\"`)
|
||||
titleEl.innerText = event.data;
|
||||
ready();
|
||||
});
|
||||
|
||||
eventSource.addEventListener("error", () => {
|
||||
eventSource.removeEventListener("error");
|
||||
eventSource.close();
|
||||
console.error("Connection lost, or an error has occurred.");
|
||||
console.log("Attempting to reconnect...");
|
||||
setTimeout(() => {
|
||||
updateTitle();
|
||||
}, 1000);
|
||||
});
|
||||
});
|
||||
}
|
||||
updateTitle();
|
||||
Loading…
Add table
Add a link
Reference in a new issue