From cb68350b860de90d98b38da5b16bee823474ebaa Mon Sep 17 00:00:00 2001 From: "prompt.ac/@jeffrey" Date: Tue, 8 Sep 2026 22:40:48 -0400 Subject: [PATCH] chat: keep pruttivox on the normal frame pump --- .../public/aesthetic.computer/disks/chat.mjs | 29 ++++++------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/system/public/aesthetic.computer/disks/chat.mjs b/system/public/aesthetic.computer/disks/chat.mjs index 2d00901674..457b295c59 100644 --- a/system/public/aesthetic.computer/disks/chat.mjs +++ b/system/public/aesthetic.computer/disks/chat.mjs @@ -307,26 +307,24 @@ function messageHitWidth(layout) { return Math.max(layout.width, voxRight); } -function voxStop(api) { +function voxStop() { if (!vox) return; vox?.playing?.kill?.(0.05); vox = null; - api?.needsPaint?.(); } async function voxToggle(message, api) { if (vox && vox.messageId === message.id) { - voxStop(api); + voxStop(); return; } - voxStop(api); + voxStop(); const my = (vox = { messageId: message.id, phase: "loading", wordIndex: -1, prefix: (message.from || "").length + 1, // fullMessage = from + " " + text }); - api.needsPaint?.(); try { const res = await fetch(`/api/pruttivox?id=${encodeURIComponent(message.id)}`); if (!res.ok) throw new Error(`pruttivox ${res.status}`); @@ -339,22 +337,15 @@ async function voxToggle(message, api) { if (vox !== my) return; my.playing = api.sound.play(sfx, undefined, { kill: () => { - if (vox === my) { - vox = null; - api.needsPaint?.(); - } + if (vox === my) vox = null; }, }); my.startedAt = performance.now(); my.phase = "playing"; - api.needsPaint?.(); console.log("🗣️ Vox playing:", message.id, my.words.length, "words"); } catch (err) { console.warn("🗣️ Vox failed:", err); - if (vox === my) { - vox = null; - api.needsPaint?.(); - } + if (vox === my) vox = null; } } @@ -4475,10 +4466,10 @@ function act( } function sim({ api, num, send, net, store }) { - // 🗣️ Advance the vox karaoke while a message is being spoken. The chip and - // highlight are discrete states, so repaint only when one changes. Asking - // for a frame on every sim tick makes the renderer expose half-drained - // command batches as visible flicker on dense laklok screens. + // 🗣️ Advance the vox karaoke while a message is being spoken. Chat's + // paint loop is already continuous, so changing state here is enough. A + // second needsPaint request races the normal frame pump and briefly exposes + // a half-painted dense laklok screen at each karaoke transition. // The karaoke clocks on wall time from play start — the sfx progress API // never answers (it fails for the stock `sfx` piece too), and for short // clips at speed 1.0 the word timestamps need no correction. The kill @@ -4487,7 +4478,6 @@ function sim({ api, num, send, net, store }) { const t = (performance.now() - vox.startedAt) / 1000; if (t > (vox.duration || 0) + 1.5) { vox = null; - api.needsPaint?.(); } else { let index = -1; for (let i = 0; i < vox.words.length; i += 1) { @@ -4496,7 +4486,6 @@ function sim({ api, num, send, net, store }) { } if (index !== vox.wordIndex) { vox.wordIndex = index; - api.needsPaint?.(); } } } -- 2.51.2