Add progress bar

This commit is contained in:
Henry Hiles 2026-01-04 16:59:51 -05:00
commit e44850ff2d
No known key found for this signature in database
3 changed files with 114 additions and 85 deletions

View file

@ -4,29 +4,36 @@ import "../styles/index.css"
--- ---
<Layout> <Layout>
<button id="play"> <section id="guesses">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"> <span></span>
<path <span></span>
d="M320-273v-414q0-17 12-28.5t28-11.5q5 0 10.5 1.5T381-721l326 207q9 6 13.5 15t4.5 19q0 10-4.5 19T707-446L381-239q-5 3-10.5 4.5T360-233q-16 0-28-11.5T320-273Z" <span></span>
></path> <span class="correct">The Correct Answer - Queen</span>
</svg> </section>
</button> <div>
<section id="bar"> <button id="play">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960">
<path
d="M320-273v-414q0-17 12-28.5t28-11.5q5 0 10.5 1.5T381-721l326 207q9 6 13.5 15t4.5 19q0 10-4.5 19T707-446L381-239q-5 3-10.5 4.5T360-233q-16 0-28-11.5T320-273Z"
></path>
</svg>
</button>
<div id="bars"> <div id="bars">
<div></div> <div></div>
<div></div> <div></div>
<div></div> <div></div>
<div id="available"><div id="played"></div></div> <div id="available"></div>
<div id="played"></div>
</div> </div>
</section> <button id="skip">
<button id="skip"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" ><path
><path d="M660-280v-400q0-17 11.5-28.5T700-720q17 0 28.5 11.5T740-680v400q0 17-11.5 28.5T700-240q-17 0-28.5-11.5T660-280Zm-440-35v-330q0-18 12-29t28-11q5 0 11 1t11 5l248 166q9 6 13.5 14.5T548-480q0 10-4.5 18.5T530-447L282-281q-5 4-11 5t-11 1q-16 0-28-11t-12-29Z"
d="M660-280v-400q0-17 11.5-28.5T700-720q17 0 28.5 11.5T740-680v400q0 17-11.5 28.5T700-240q-17 0-28.5-11.5T660-280Zm-440-35v-330q0-18 12-29t28-11q5 0 11 1t11 5l248 166q9 6 13.5 14.5T548-480q0 10-4.5 18.5T530-447L282-281q-5 4-11 5t-11 1q-16 0-28-11t-12-29Z" ></path></svg
></path></svg >
> </button>
</button> </div>
</Layout> </Layout>
<script> <script>
@ -37,13 +44,12 @@ import "../styles/index.css"
await auth.init({ await auth.init({
clientId: "NkcXqihOmrfZdBla", clientId: "NkcXqihOmrfZdBla",
clientSecret: "e6ldlWH48BEBOUZV1uIyIWJOf1KUGUEeH6qHkFvNjeU=", clientSecret: "e6ldlWH48BEBOUZV1uIyIWJOf1KUGUEeH6qHkFvNjeU=",
credentialsStorageKey: "key", credentialsStorageKey: "ZvZbtTWzx5@1zfiWUluxWD9@di17e1da",
}) })
player.setCredentialsProvider(auth.credentialsProvider) player.setCredentialsProvider(auth.credentialsProvider)
player.setEventSender(eventProducer) player.setEventSender(eventProducer)
// TODO: Use css anim for progress
class ExtendableTimeout { class ExtendableTimeout {
private timerId: ReturnType<typeof setTimeout> private timerId: ReturnType<typeof setTimeout>
private timeStart: number private timeStart: number
@ -70,28 +76,31 @@ import "../styles/index.css"
} }
const play = document.querySelector("#play") const play = document.querySelector("#play")
const played = document.querySelector("#played")
const skip = document.querySelector("#skip") const skip = document.querySelector("#skip")
const available = document.querySelector("#available") as HTMLDivElement const available = document.querySelector("#available")
let phase = 1 let phase = 1
let timer: ExtendableTimeout | null let timer: ExtendableTimeout | null
const getTimeout = () => 2 ** phase * 1000 const getTimeout = (phase: number) => (2 ** phase - 1) * 1000
const playVideo = async () => { const playVideo = async () => {
await player.load({ await player.load({
productId: "3188631", productId: "36737274",
productType: "track", productType: "track",
sourceId: "3188629", sourceId: "",
sourceType: "ALBUM", sourceType: "",
}) })
player.play() await player.play()
played?.classList.add("playing")
timer?.cancel() timer?.cancel()
timer = new ExtendableTimeout(() => { timer = new ExtendableTimeout(() => {
player.pause() player.pause()
timer = null timer = null
}, getTimeout()) played?.classList.remove("playing")
}, getTimeout(phase))
} }
play?.addEventListener("click", playVideo) play?.addEventListener("click", playVideo)
@ -100,13 +109,13 @@ import "../styles/index.css"
if (phase >= 4) return alert("FAIL!!!!") if (phase >= 4) return alert("FAIL!!!!")
phase += 1 phase += 1
//@ts-expect-error // @ts-expect-error
available.style["grid-column-end"] = phase + 1 available.style["grid-column-end"] = phase + 1
if (timer == null) { if (timer == null) {
playVideo() playVideo()
} else { } else {
timer.extend(getTimeout()) timer.extend(getTimeout(phase))
} }
}) })
</script> </script>

View file

@ -1,51 +1,74 @@
#bar { main > * {
display: flex;
width: 100%;
justify-content: center;
align-items: center;
width: min(45rem, 100%);
}
#guesses {
flex-direction: column;
gap: 2rem;
& span {
display: flex;
justify-content: center;
align-items: center;
font-weight: bold;
background-color: #000;
height: 2.4rem;
width: 100%;
border-radius: 2rem;
&.correct {
background-image: linear-gradient(
to bottom right,
var(--brand-pink) 0%,
var(--brand-purple) 100%
);
}
}
}
#bars {
display: grid;
grid-template-columns: 1fr 2fr 4fr 8fr;
justify-content: center;
width: min(40rem, 100%); width: min(40rem, 100%);
position: relative;
& #bars { & * {
display: grid; background-color: rgba(255, 255, 255, 20%);
grid-template-columns: 1fr 2fr 4fr 8fr; height: 1rem;
gap: 0.3rem; border-radius: 1rem;
grid-row: 1;
& * {
background-color: rgba(255, 255, 255, 20%);
height: 1rem;
border-radius: 1rem;
grid-row: 1;
}
& #available {
grid-column-start: 1;
width: 100%;
}
} }
& #available { & #available {
background-color: white; background-color: white;
width: 0; grid-column-start: 1;
}
}
.frame-container {
position: relative;
@supports (-moz-appearance: none) {
display: none;
}
& span {
pointer-events: none;
}
& iframe {
position: absolute;
width: 100%; width: 100%;
height: 100%; }
border: none;
z-index: -2;
pointer-events: all;
clip-path: inset(90% 0 0 90%); & #played {
transform-origin: bottom right; position: absolute;
transform: scale(10); background: linear-gradient(
to bottom right,
#cc56d0 0%,
var(--brand-purple) 100%
);
grid-column: 1 / -1;
width: 0%;
transition: none;
&.playing {
transition: width 15s linear;
width: 100%;
}
} }
} }

View file

@ -1,13 +1,17 @@
html, html,
body { body {
display: flex;
flex-direction: column;
margin: 0; margin: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
:root { :root {
background: linear-gradient(black, rgb(18, 2, 38));
--brand-purple: #6e06ff; --brand-purple: #6e06ff;
--brand-pink: #cc56d0;
background: linear-gradient(black, rgb(18, 2, 38));
font-family: sans-serif; font-family: sans-serif;
} }
@ -18,6 +22,7 @@ img {
} }
nav { nav {
position: absolute;
display: flex; display: flex;
align-items: center; align-items: center;
padding: 2rem 3rem; padding: 2rem 3rem;
@ -35,12 +40,15 @@ nav {
main { main {
color: white; color: white;
display: flex; display: flex;
flex-direction: column;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
gap: 1rem;
flex-grow: 1;
} }
button, button {
.fake-button {
--border-radius: 2rem; --border-radius: 2rem;
position: relative; position: relative;
background: white; background: white;
@ -60,16 +68,12 @@ button,
background: rgb(211, 211, 211); background: rgb(211, 211, 211);
} }
&.fake-button {
pointer-events: none;
}
& svg { & svg {
width: 2.2rem; width: 2.2rem;
} }
} }
:is(button, .fake-button)::before { button::before {
--border-size: 5px; --border-size: 5px;
content: ""; content: "";
z-index: -1; z-index: -1;
@ -78,7 +82,7 @@ button,
height: 100%; height: 100%;
background-image: linear-gradient( background-image: linear-gradient(
to bottom right, to bottom right,
#cc56d0 0%, var(--brand-pink) 0%,
var(--brand-purple) 100% var(--brand-purple) 100%
); );
padding: var(--border-size); padding: var(--border-size);
@ -86,10 +90,3 @@ button,
left: calc(var(--border-size) * -1); left: calc(var(--border-size) * -1);
position: absolute; position: absolute;
} }
.fake-button-container {
cursor: pointer;
&:hover {
filter: brightness(80%);
}
}