diff --git a/site/src/components/PlayerControls.astro b/site/src/components/PlayerControls.astro
new file mode 100644
index 0000000..72ebaa6
--- /dev/null
+++ b/site/src/components/PlayerControls.astro
@@ -0,0 +1,87 @@
+---
+
+---
+
+
+
+
+
+
diff --git a/site/src/lib/browser/animations.ts b/site/src/lib/browser/animations.ts
new file mode 100644
index 0000000..8ba70de
--- /dev/null
+++ b/site/src/lib/browser/animations.ts
@@ -0,0 +1,43 @@
+let paused = false;
+
+export const getAnimationState = () => {
+ return paused ? "paused" : "playing";
+};
+
+const updatePostAnimations = (playState: "paused" | "running") => {
+ document.querySelectorAll(".post").forEach((post) => {
+ (post as HTMLDivElement).style.animationPlayState = playState;
+ });
+
+ document.querySelectorAll(".post-load-bar-fill").forEach((postBar) => {
+ (postBar as HTMLDivElement).style.animationPlayState = playState;
+ });
+};
+
+const pauseAllAnimations = () => {
+ paused = true;
+ // const animations = document.getAnimations();
+ // animations.forEach((anim) => anim.pause());
+ updatePostAnimations("paused");
+ (document.querySelector("#filledchart") as SVGSVGElement).pauseAnimations();
+};
+
+const resumeAllAnimations = () => {
+ paused = false;
+ // const animations = document.getAnimations();
+ // animations.forEach((anim) => anim.play());
+ updatePostAnimations("running");
+ (document.querySelector("#filledchart") as SVGSVGElement).unpauseAnimations();
+};
+
+export const toggleAnimationState = () => {
+ const state = getAnimationState();
+ switch (state) {
+ case "paused":
+ resumeAllAnimations();
+ break;
+ case "playing":
+ pauseAllAnimations();
+ break;
+ }
+};
diff --git a/site/src/lib/browser/posts.ts b/site/src/lib/browser/posts.ts
index ebfe9c5..91b7d15 100644
--- a/site/src/lib/browser/posts.ts
+++ b/site/src/lib/browser/posts.ts
@@ -7,10 +7,6 @@ export const handlePostEvents = () => {
const posts: NodeListOf = document.querySelectorAll(".post");
const postContainer = document.querySelector(".posts");
if (postContainer) {
- // postContainer.addEventListener("scroll", () => {
- // console.log('>', event)
- // });
-
posts.forEach((post) => {
post.addEventListener("animationstart", (event) => {
const postDiv = event.target as HTMLDivElement | null;
@@ -19,6 +15,11 @@ export const handlePostEvents = () => {
return;
}
+ if (postDiv.classList.contains("post") === false) {
+ // child events may bubble up
+ return;
+ }
+
const top =
postDiv.getBoundingClientRect().top -
postTopOffset +
diff --git a/site/src/pages/[...enabler].astro b/site/src/pages/[...enabler].astro
index 1b32760..7891aa8 100644
--- a/site/src/pages/[...enabler].astro
+++ b/site/src/pages/[...enabler].astro
@@ -5,6 +5,7 @@ import Layout from "../layouts/Layout.astro";
import KilledGraph from "../generated/killed.astro";
import PostTypeIcon from "../components/PostTypeIcon.astro";
import OpacityOverlay from "../components/OpacityOverlay.astro";
+import PlayerControls from "../components/PlayerControls.astro";
import { getTimeline } from "../lib/server/timeline";
import { getSvgDomain } from "../lib/server/svg";
import { getEnhancedPosts } from "../lib/server/posts";
@@ -42,6 +43,7 @@ const {