Merge branch 'perf/lag': dashboard lag fixes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	client/src/components/Sagi/PetSprite.tsx
#	client/src/components/Sagi/useSagiBrain.ts
This commit is contained in:
2026-10-14 12:26:41 +07:00
36 changed files with 676 additions and 101 deletions
+7 -1
View File
@@ -63,6 +63,8 @@ const ACTION_ROW: Record<PetAction, number> = { "run-right": 1, "run-left": 2, w
/** A moment's row: wave, jump, failed, waiting, review. It outranks the mood,
* and the user's own action outranks it. */
const MOMENT_ROW: Record<PetMoment, number> = { wave: 3, jump: 4, fail: 5, wait: 6, review: 8 };
/** Loops of a row before the sprite rests on its first frame. */
const SPRITE_LOOPS = 4;
export function PetSprite({
id,
@@ -102,13 +104,17 @@ export function PetSprite({
const own = play(row, sleeping ? SLEEP_SLOWDOWN : 1);
let list = MOMENTS.has(row) ? [...own, ...own, ...own] : own;
let i = 0;
let loops = 0;
let timer = 0;
// `i` always indexes `list`: it wraps at its end.
// `i` always indexes `list`: it wraps at its end. A few loops, then the
// first frame rests — a sprite that never stops re-paints the page several
// times a second for as long as it is open; a new mood or action plays again.
const tick = () => {
timer = window.setTimeout(() => {
if (++i === list.length) {
i = 0;
if (MOMENTS.has(row)) list = play(0);
if (++loops >= SPRITE_LOOPS) return setCell(list[0]!);
}
setCell(list[i]!);
tick();