- commit
- db5c0a4
- parent
- 6e77947
- author
- Eric Bower
- date
- 2024-10-08 02:47:22 +0000 UTC
style(pubsub): make it pop
12 files changed,
+88,
-13
+1,
-8
1@@ -40,14 +40,7 @@ func createStaticRoutes() []shared.Route {
2 shared.NewRoute("GET", "/apple-touch-icon.png", serveFile("apple-touch-icon.png", "image/png")),
3 shared.NewRoute("GET", "/favicon.ico", serveFile("favicon.ico", "image/x-icon")),
4 shared.NewRoute("GET", "/robots.txt", serveFile("robots.txt", "text/plain")),
5- shared.NewRoute("GET", "/send-output.gif", serveFile("send-output.gif", "image/gif")),
6- shared.NewRoute("GET", "/send-file.gif", serveFile("send-file.gif", "image/gif")),
7- shared.NewRoute("GET", "/multi-sub.gif", serveFile("multi-sub.gif", "image/gif")),
8- shared.NewRoute("GET", "/multi-pub.gif", serveFile("multi-pub.gif", "image/gif")),
9- shared.NewRoute("GET", "/multi-pub-sub.gif", serveFile("multi-pub-sub.gif", "image/gif")),
10- shared.NewRoute("GET", "/pipe-chat.gif", serveFile("pipe-chat.gif", "image/gif")),
11- shared.NewRoute("GET", "/pipe-cmd-output.gif", serveFile("pipe-cmd-output.gif", "image/gif")),
12- shared.NewRoute("GET", "/pipe-reverse-shell.gif", serveFile("pipe-reverse-shell.gif", "image/gif")),
13+ shared.NewRoute("GET", "/anim.js", serveFile("anim.js", "text/javascript")),
14 }
15 }
16
+1,
-0
1@@ -12,6 +12,7 @@
2 {{template "meta" .}}
3
4 <link rel="stylesheet" href="https://pico.sh/smol.css" />
5+ <script src="/anim.js"></script>
6 </head>
7 <body {{template "attrs" .}}>{{template "body" .}}</body>
8 </html>
+7,
-5
1@@ -15,13 +15,15 @@
2 {{define "attrs"}}class="container-sm"{{end}}
3
4 {{define "body"}}
5-<header class="flex flex-col items-center gap">
6- <img src="https://pico.sh/logo.svg" alt="pico logo" width="50" height="50" />
7+<header class="flex flex-col items-center gap-2">
8+ <div class="flex flex-col">
9+ <img src="https://pico.sh/logo.svg" alt="pico logo" width="50" height="50" />
10+ <canvas id="canvas" width="50" height="50"></canvas>
11+ <hr width="100%" class="m-0" />
12+ </div>
13 <h1 class="text-2xl font-bold text-center">Authenticated *nix pipes over ssh</h1>
14 </header>
15
16-<hr />
17-
18 <article class="flex flex-col gap-2">
19 <div>
20 <p>
21@@ -271,7 +273,7 @@
22 <h2 class="text-xl">Latest posts</h2>
23 <div class="flex items-center">
24 <div class="mr font-italic">2024-10-06</div>
25- <div><a href="https://blog.pico.sh/pubsub">announcing pubsub service</a></div>
26+ <div><a href="https://blog.pico.sh/pubsub">pipe: our pubsub ssh service</a></div>
27 </div>
28 </div>
29
+79,
-0
1@@ -0,0 +1,79 @@
2+document.addEventListener("DOMContentLoaded", init);
3+const raf = window.requestAnimationFrame;
4+
5+function init() {
6+ const canvas = document.getElementById("canvas");
7+ const ctx = canvas.getContext("2d");
8+ const data = {
9+ ctx,
10+ // speed of movement (higher = faster)
11+ speed: 200,
12+ frame: 1,
13+ prev: 0,
14+ cur: 0,
15+ // boundary balls can traverse inside canvas
16+ minY: -20,
17+ maxY: canvas.height + 20,
18+ // balls
19+ entities: [
20+ { x: 20, y: 0, mod: 1 },
21+ // { x: 25, y: canvas.height / 2, mod: 1 },
22+ { x: 35, y: canvas.height, mod: -1 },
23+ ],
24+ };
25+
26+ raf(tick(data));
27+}
28+
29+function tick(data) {
30+ return (ms) => {
31+ const prev = data.cur;
32+ const cur = ms * 0.001;
33+ const next = {
34+ ...data,
35+ prev,
36+ cur,
37+ frame: data.frame + 1,
38+ delta: cur - prev,
39+ };
40+ return loop(next);
41+ };
42+}
43+
44+function loop(data) {
45+ const { ctx, entities, speed, delta, minY, maxY } = data;
46+ const width = ctx.canvas.width;
47+ const height = ctx.canvas.height;
48+ ctx.clearRect(0, 0, width, height);
49+
50+ for (let i = 0; i < entities.length; i += 1) {
51+ const entity = entities[i];
52+ const x = entity.x;
53+ const y = entity.y + (speed * delta * entity.mod);
54+ const nextMod = () => {
55+ if (y < minY) return 1;
56+ if (y > maxY) return -1;
57+ return entity.mod;
58+ };
59+
60+ // grace for entire ball to leave scene
61+ // const buffer = 25
62+ // dont bother drawing circle if outside canvas
63+ // if (y + buffer >= 0 && y - buffer <= height) {
64+ ball(ctx, x, y);
65+ // }
66+
67+ entities[i].x = x;
68+ entities[i].y = y;
69+ entities[i].mod = nextMod();
70+ }
71+
72+ raf(tick(data));
73+}
74+
75+function ball(ctx, x, y) {
76+ ctx.fillStyle = "#f2f2f2";
77+ ctx.beginPath();
78+ ctx.arc(x, y, 5, 0, 2 * Math.PI);
79+ ctx.fill();
80+}
+0,
-0
+0,
-0
+0,
-0
+0,
-0
+0,
-0
+0,
-0
+0,
-0
+0,
-0