summaryrefslogtreecommitdiff
path: root/fig-frontend-client
diff options
context:
space:
mode:
authorLLLL Colonq <llll@colonq>2024-03-29 00:59:53 -0400
committerLLLL Colonq <llll@colonq>2024-03-29 00:59:53 -0400
commit70d50561b19b4161b85ec1b00c31e5678502688b (patch)
tree39365fd96e0021c8caa9500624664b846a4e020c /fig-frontend-client
parentdec476ab9b8602225964cfa534bb004676ff6419 (diff)
Update catchphrases
Diffstat (limited to 'fig-frontend-client')
-rw-r--r--fig-frontend-client/index-template.html2
-rw-r--r--fig-frontend-client/main.css14
-rw-r--r--fig-frontend-client/main.js144
-rw-r--r--fig-frontend-client/src/Main.purs16
-rw-r--r--fig-frontend-client/src/Model.js108
-rw-r--r--fig-frontend-client/src/Model.purs10
6 files changed, 266 insertions, 28 deletions
diff --git a/fig-frontend-client/index-template.html b/fig-frontend-client/index-template.html
index f306205..f793ddd 100644
--- a/fig-frontend-client/index-template.html
+++ b/fig-frontend-client/index-template.html
@@ -13,6 +13,7 @@ CONFIG_SUBST
</head>
<body>
<!-- RINGBEARER -->
+ <canvas id="lcolonq-canvas"></canvas>
<div id="lcolonq-title">
<span class="lcolonq-letter" id="lcolonq-letter-0">L</span><span class="lcolonq-letter" id="lcolonq-letter-1">C</span><span class="lcolonq-letter" id="lcolonq-letter-2">O</span><span class="lcolonq-letter" id="lcolonq-letter-3">L</span><span class="lcolonq-letter" id="lcolonq-letter-4">O</span><span class="lcolonq-letter" id="lcolonq-letter-5">N</span><span class="lcolonq-letter" id="lcolonq-letter-6">Q</span>
<div id="lcolonq-subtitle">
@@ -35,6 +36,5 @@ CONFIG_SUBST
<audio id="lcolonq-audio-voice-4" src="assets/voice/4.wav"></audio>
<audio id="lcolonq-audio-voice-5" src="assets/voice/5.wav"></audio>
<audio id="lcolonq-audio-voice-6" src="assets/voice/6.wav"></audio>
- <!-- <canvas id="lcolonq-canvas"></canvas> -->
</body>
</html>
diff --git a/fig-frontend-client/main.css b/fig-frontend-client/main.css
index 22368c3..3305e19 100644
--- a/fig-frontend-client/main.css
+++ b/fig-frontend-client/main.css
@@ -50,6 +50,8 @@ body {
#lcolonq-subtitle {
font-size: 5vw;
margin-top: -5vw;
+ margin-right: 12vw;
+ text-align: right;
}
#lcolonq-header {
@@ -98,16 +100,10 @@ body {
#lcolonq-canvas {
position: absolute;
- top: 0px;
- bottom: 0px;
+ bottom: 2rem;
left: 0px;
- right: 0px;
- width: 100%;
- height: 100%;
-}
-
-button {
- color: red;
+ width: 832px;
+ height: 832px;
}
.right {
diff --git a/fig-frontend-client/main.js b/fig-frontend-client/main.js
index 38024ce..67e726e 100644
--- a/fig-frontend-client/main.js
+++ b/fig-frontend-client/main.js
@@ -2679,6 +2679,112 @@ var fetch2 = function() {
};
};
+// output/Model/foreign.js
+var canvas = document.getElementById("lcolonq-canvas");
+var socket = new WebSocket("wss://colonq.computer/bullfrog/api/channel/listen/model");
+var currentFrame = null;
+socket.addEventListener("open", (ev) => {
+ console.log("connected");
+});
+async function decompress(blob3) {
+ let ds = new DecompressionStream("gzip");
+ let stream = blob3.stream();
+ let out = await new Response(stream.pipeThrough(ds));
+ return out.arrayBuffer();
+}
+function readCell(dv, base) {
+ let cell = {};
+ let o = base;
+ if (dv.getUint8(o) == 0) {
+ return [{ type: "bg" }, o + 1];
+ } else {
+ cell.type = "fg";
+ cell.custom = dv.getUint8(o + 1);
+ cell.r = dv.getUint8(o + 2);
+ cell.g = dv.getUint8(o + 3);
+ cell.b = dv.getUint8(o + 4);
+ cell.g0 = dv.getUint32(o + 5);
+ if (dv.getUint8(o + 9) == 0) {
+ return [cell, o + 10];
+ } else {
+ cell.g1 = dv.getUint32(o + 10);
+ return [cell, o + 14];
+ }
+ }
+}
+function readKeyframe(dv, base) {
+ let ret = [];
+ let o = base;
+ for (let idx = 0; idx < 64 * 64; ++idx) {
+ let res = readCell(dv, o);
+ ret.push(res[0]);
+ o = res[1];
+ }
+ currentFrame = ret;
+}
+function readDiff(dv, base) {
+ if (currentFrame) {
+ let len = dv.getUint32(base);
+ let o = base + 4;
+ for (let idx = 0; idx < len; ++idx) {
+ let x = dv.getUint8(o);
+ let y = dv.getUint8(o + 1);
+ let c = readCell(dv, o + 2);
+ currentFrame[x + y * 64] = c[0];
+ o = c[1];
+ }
+ }
+}
+function readPacket(dv) {
+ if (dv.getUint8(0) == 0) {
+ readKeyframe(dv, 1);
+ } else {
+ readDiff(dv, 1);
+ }
+}
+function renderCellCanvas(ctx2, x, y, c) {
+ if (c) {
+ let msg = c.g1 ? String.fromCodePoint(c.g0, c.g1) : String.fromCodePoint(c.g0);
+ if (msg.trim().length) {
+ ctx2.fillStyle = "black";
+ ctx2.fillRect(13 * y, 13 * x, 13, 13);
+ ctx2.fillStyle = `rgba(${c.r}, ${c.g}, ${c.b}, 1.0)`;
+ ctx2.fillText(msg, 13 * y, 13 * x + 10);
+ }
+ }
+}
+function renderCanvas() {
+ if (canvas.width != canvas.clientWidth) {
+ canvas.width = canvas.clientWidth;
+ }
+ if (canvas.height != canvas.clientHeight) {
+ canvas.height = canvas.clientHeight;
+ }
+ if (currentFrame) {
+ let ctx2 = canvas.getContext("2d");
+ ctx2.clearRect(0, 0, canvas.width, canvas.height);
+ ctx2.font = "12px Iosevka Comfy";
+ for (let y = 0; y < 64; ++y) {
+ for (let x = 0; x < 64; ++x) {
+ renderCellCanvas(ctx2, x, y, currentFrame[x * 64 + y]);
+ }
+ }
+ }
+}
+var _startModel = () => {
+ socket.addEventListener("message", async (ev) => {
+ let arr = await decompress(ev.data);
+ let view = new DataView(arr);
+ readPacket(view);
+ renderCanvas();
+ });
+};
+
+// output/Model/index.js
+var startModel = function(dictMonadEffect) {
+ return liftEffect(dictMonadEffect)(_startModel);
+};
+
// output/Web.DOM.Document/foreign.js
var getEffProp = function(name15) {
return function(doc) {
@@ -2819,9 +2925,10 @@ function document2(window2) {
// output/Main/index.js
var map6 = /* @__PURE__ */ map(functorEffect);
-var discard2 = /* @__PURE__ */ discard(discardUnit)(bindAff);
var bind4 = /* @__PURE__ */ bind(bindAff);
var fetch3 = /* @__PURE__ */ fetch2()()(/* @__PURE__ */ toCoreRequestOptionsRowRo()()(toCoreRequestOptionsHelpe));
+var discard2 = /* @__PURE__ */ discard(discardUnit)(bindAff);
+var startModel2 = /* @__PURE__ */ startModel(monadEffectAff);
var for_2 = /* @__PURE__ */ for_(applicativeAff)(foldableArray);
var show2 = /* @__PURE__ */ show(showInt);
var playVoice2 = /* @__PURE__ */ playVoice(monadEffectEffect);
@@ -2872,20 +2979,29 @@ var byId = function(dictMonadEffect) {
};
};
var byId1 = /* @__PURE__ */ byId(monadEffectAff);
+var updateSubtitle = /* @__PURE__ */ bind4(/* @__PURE__ */ byId1("lcolonq-subtitle"))(function(subtitle) {
+ return bind4(fetch3(apiServer + "/catchphrase")({}))(function(v) {
+ return bind4(v.text)(setText1(subtitle));
+ });
+});
var main = /* @__PURE__ */ launchAff_(/* @__PURE__ */ discard2(/* @__PURE__ */ liftEffect(monadEffectAff)(/* @__PURE__ */ log("hi")))(function() {
- return bind4(byId1("lcolonq-marquee"))(function(marq) {
- return bind4(fetch3(apiServer + "/motd")({}))(function(v) {
- return discard2(bind4(v.text)(setText1(marq)))(function() {
- return bind4(byId1("lcolonq-subtitle"))(function(subtitle) {
- return bind4(fetch3(apiServer + "/catchphrase")({}))(function(v1) {
- return discard2(bind4(v1.text)(setText1(subtitle)))(function() {
- return for_2(range2(0)(6))(function(i) {
- return bind4(byId1("lcolonq-letter-" + show2(i)))(function(letter) {
- return discard2(listen1(letter)("click")(function(_ev) {
- return playVoice2(true)(i);
- }))(function() {
- return listen1(letter)("mouseover")(function(_ev) {
- return playVoice2(false)(i);
+ return discard2(startModel2)(function() {
+ return bind4(byId1("lcolonq-marquee"))(function(marq) {
+ return bind4(fetch3(apiServer + "/motd")({}))(function(v) {
+ return discard2(bind4(v.text)(setText1(marq)))(function() {
+ return discard2(updateSubtitle)(function() {
+ return bind4(byId1("lcolonq-subtitle"))(function(subtitle) {
+ return discard2(listen1(subtitle)("click")(function(_ev) {
+ return launchAff_(updateSubtitle);
+ }))(function() {
+ return for_2(range2(0)(6))(function(i) {
+ return bind4(byId1("lcolonq-letter-" + show2(i)))(function(letter) {
+ return discard2(listen1(letter)("click")(function(_ev) {
+ return playVoice2(true)(i);
+ }))(function() {
+ return listen1(letter)("mouseover")(function(_ev) {
+ return playVoice2(false)(i);
+ });
});
});
});
diff --git a/fig-frontend-client/src/Main.purs b/fig-frontend-client/src/Main.purs
index 2a73c4f..cb06b86 100644
--- a/fig-frontend-client/src/Main.purs
+++ b/fig-frontend-client/src/Main.purs
@@ -2,9 +2,8 @@ module Main where
import Prelude
-import Config as Config
import Audio as Audio
-
+import Config as Config
import Data.Array as Array
import Data.Maybe (Maybe(..))
import Data.Traversable (for, for_)
@@ -14,6 +13,7 @@ import Effect.Class (class MonadEffect, liftEffect)
import Effect.Console (log)
import Effect.Exception (throw)
import Fetch (fetch)
+import Model (startModel)
import Web.DOM as DOM
import Web.DOM.Document as DOM.Doc
import Web.DOM.Element as DOM.El
@@ -41,16 +41,24 @@ listen e ev f = do
setText :: forall m. MonadEffect m => DOM.Element -> String -> m Unit
setText e s = liftEffect $ DOM.Node.setTextContent s $ DOM.El.toNode e
+updateSubtitle :: Aff Unit
+updateSubtitle = do
+ subtitle <- byId "lcolonq-subtitle"
+ { text: catchphrase } <- fetch (Config.apiServer <> "/catchphrase") {}
+ catchphrase >>= setText subtitle
+
main :: Effect Unit
main = launchAff_ do
liftEffect $ log "hi"
+ startModel
marq <- byId "lcolonq-marquee"
{ text: motd } <- fetch (Config.apiServer <> "/motd") {}
motd >>= setText marq
+ updateSubtitle
subtitle <- byId "lcolonq-subtitle"
- { text: catchphrase } <- fetch (Config.apiServer <> "/catchphrase") {}
- catchphrase >>= setText subtitle
+ listen subtitle "click" \_ev -> do
+ launchAff_ updateSubtitle
for_ (Array.range 0 6) \i -> do
letter <- byId $ "lcolonq-letter-" <> show i
diff --git a/fig-frontend-client/src/Model.js b/fig-frontend-client/src/Model.js
new file mode 100644
index 0000000..299c645
--- /dev/null
+++ b/fig-frontend-client/src/Model.js
@@ -0,0 +1,108 @@
+let canvas = document.getElementById("lcolonq-canvas");
+let socket = new WebSocket("wss://colonq.computer/bullfrog/api/channel/listen/model");
+let currentFrame = null;
+
+socket.addEventListener("open", (ev) => {
+ console.log("connected");
+});
+
+async function decompress(blob) {
+ let ds = new DecompressionStream("gzip");
+ let stream = blob.stream();
+ let out = await new Response(stream.pipeThrough(ds));
+ return out.arrayBuffer();
+}
+
+function readCell(dv, base) {
+ let cell = {};
+ let o = base;
+ if (dv.getUint8(o) == 0) {
+ return [{type: "bg"}, o + 1];
+ } else {
+ cell.type = "fg";
+ cell.custom = dv.getUint8(o + 1);
+ cell.r = dv.getUint8(o + 2);
+ cell.g = dv.getUint8(o + 3);
+ cell.b = dv.getUint8(o + 4);
+ cell.g0 = dv.getUint32(o + 5);
+ if (dv.getUint8(o + 9) == 0) {
+ return [cell, o + 10];
+ } else {
+ cell.g1 = dv.getUint32(o + 10);
+ return [cell, o + 14];
+ }
+ }
+}
+
+function readKeyframe(dv, base) {
+ let ret = [];
+ let o = base;
+ for (let idx = 0; idx < (64 * 64); ++idx) {
+ let res = readCell(dv, o);
+ ret.push(res[0]);
+ o = res[1];
+ }
+ currentFrame = ret;
+}
+
+function readDiff(dv, base) {
+ if (currentFrame) {
+ let len = dv.getUint32(base);
+ let o = base + 4;
+ for (let idx = 0; idx < len; ++idx) {
+ let x = dv.getUint8(o);
+ let y = dv.getUint8(o + 1);
+ let c = readCell(dv, o + 2);
+ currentFrame[x + (y * 64)] = c[0];
+ o = c[1];
+ }
+ }
+}
+
+function readPacket(dv) {
+ if (dv.getUint8(0) == 0) {
+ readKeyframe(dv, 1);
+ } else {
+ readDiff(dv, 1);
+ }
+}
+
+function renderCellCanvas(ctx, x, y, c) {
+ if (c) {
+ let msg = c.g1 ? String.fromCodePoint(c.g0, c.g1) : String.fromCodePoint(c.g0);
+ if (msg.trim().length) {
+ ctx.fillStyle = "black";
+ ctx.fillRect(13 * y, 13 * x, 13, 13);
+ ctx.fillStyle = `rgba(${c.r}, ${c.g}, ${c.b}, 1.0)`;
+ ctx.fillText(msg, 13 * y, 13 * x + 10);
+ }
+ }
+}
+
+function renderCanvas() {
+ if (canvas.width != canvas.clientWidth) {
+ canvas.width = canvas.clientWidth;
+ }
+ if (canvas.height != canvas.clientHeight) {
+ canvas.height = canvas.clientHeight;
+ }
+ if (currentFrame) {
+ let ctx = canvas.getContext("2d");
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+ ctx.font = "12px Iosevka Comfy";
+ for (let y = 0; y < 64; ++y) {
+ for (let x = 0; x < 64; ++x) {
+ renderCellCanvas(ctx, x, y, currentFrame[(x * 64) + y]);
+ }
+ }
+ }
+}
+
+export const _startModel = () => {
+ socket.addEventListener("message", async (ev) => {
+ let arr = await decompress(ev.data);
+ let view = new DataView(arr);
+ readPacket(view);
+ renderCanvas();
+ });
+};
diff --git a/fig-frontend-client/src/Model.purs b/fig-frontend-client/src/Model.purs
new file mode 100644
index 0000000..a9f2888
--- /dev/null
+++ b/fig-frontend-client/src/Model.purs
@@ -0,0 +1,10 @@
+module Model where
+
+import Prelude
+
+import Effect (Effect)
+import Effect.Class (class MonadEffect, liftEffect)
+
+foreign import _startModel :: Effect Unit
+startModel :: forall m. MonadEffect m => m Unit
+startModel = liftEffect _startModel