@mingxy/opencode-mascot 0.2.8 → 0.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mingxy/opencode-mascot",
3
- "version": "0.2.8",
3
+ "version": "0.2.9",
4
4
  "description": "OpenCode TUI mascot plugin framework - customizable ASCII mascots for your terminal",
5
5
  "author": "mingxy",
6
6
  "license": "MIT",
@@ -36,6 +36,9 @@ const DEFAULT_ANIM = {
36
36
 
37
37
  const WALK_PATH = [1, 2, 3, 4, 3, 2, 1, 0, -1, -2, -3, -2, -1, 0];
38
38
 
39
+ const FLASH_COLORS = ["#FF006E", "#FFBE0B", "#8338EC", "#3A86FF", "#FB5607", "#06FFA5", "#FF4081", "#00E5FF"];
40
+ const DRAG_MSGS = ["ᶠᵃⁿᵍ!..", "ᵏᵃⁱ~..", "ᵇᵘᶠᵃⁿᵍ~..", "ʷᵒ~..", "ⁿⁱᵘ~..", "ᵃᵃ~.."];
41
+
39
42
  function getFrameLines(pack: MascotPack, frameName: string): string[] {
40
43
  const frames = pack.frames as Record<string, string[] | undefined>;
41
44
  return frames[frameName] ?? frames["default"] ?? [];
@@ -72,6 +75,19 @@ export function createAnimatedRenderer(pack: MascotPack): {
72
75
  const [walkEnabled, setWalkEnabled] = createSignal(anim.walkEnabled ?? true);
73
76
  const [dragging, setDraggingSignal] = createSignal(false);
74
77
  const [celebrate, setCelebrate] = createSignal<{ text: string; count: number } | null>(null);
78
+ const [flashColor, setFlashColor] = createSignal<string | null>(null);
79
+ const [dragMsg, setDragMsg] = createSignal<string | null>(null);
80
+
81
+ let flashTimer: ReturnType<typeof setInterval> | null = null;
82
+ let dragMsgTimer: ReturnType<typeof setInterval> | null = null;
83
+
84
+ const stopFlash = () => {
85
+ if (flashTimer) { clearInterval(flashTimer); flashTimer = null; }
86
+ };
87
+ const stopDragMsg = () => {
88
+ if (dragMsgTimer) { clearInterval(dragMsgTimer); dragMsgTimer = null; }
89
+ setDragMsg(null);
90
+ };
75
91
 
76
92
  let idleSleepTimeout: ReturnType<typeof setTimeout> | null = null;
77
93
 
@@ -230,6 +246,8 @@ export function createAnimatedRenderer(pack: MascotPack): {
230
246
  if (idleSleepTimeout) clearTimeout(idleSleepTimeout);
231
247
  if (walkInterval) clearInterval(walkInterval);
232
248
  for (const t of effectTimers) clearInterval(t);
249
+ stopFlash();
250
+ stopDragMsg();
233
251
  });
234
252
 
235
253
  // ─── Render ───
@@ -241,6 +259,8 @@ export function createAnimatedRenderer(pack: MascotPack): {
241
259
  currentState();
242
260
  dragging();
243
261
  celebrate();
262
+ flashColor();
263
+ dragMsg();
244
264
 
245
265
  for (const [, [get]] of extraSignals) {
246
266
  get();
@@ -276,11 +296,14 @@ export function createAnimatedRenderer(pack: MascotPack): {
276
296
  const top = jumpOffset();
277
297
  const left = offset > 0 ? offset : 0;
278
298
  const cel = celebrate();
299
+ const dm = dragMsg();
300
+ const color = flashColor() ?? fg;
279
301
 
280
302
  return (
281
303
  <box flexDirection="column" left={left} top={top}>
282
- {cel ? <text fg={fg}>{cel.text}</text> : null}
283
- {renderLines(lines, fg)}
304
+ {cel ? <text fg={color}>{cel.text}</text> : null}
305
+ {dm ? <text fg="#FF4081">{dm}</text> : null}
306
+ {renderLines(lines, color)}
284
307
  </box>
285
308
  );
286
309
  };
@@ -297,6 +320,15 @@ export function createAnimatedRenderer(pack: MascotPack): {
297
320
  walkTimeout = scheduleNextWalk();
298
321
  jumpTimeout = scheduleNextJump();
299
322
  }
323
+
324
+ if (s === "thinking" || s === "busy") {
325
+ stopFlash();
326
+ flashTimer = setInterval(() => {
327
+ setFlashColor(FLASH_COLORS[Math.floor(Math.random() * FLASH_COLORS.length)]);
328
+ }, 120);
329
+ } else {
330
+ stopFlash();
331
+ }
300
332
  };
301
333
 
302
334
  const toggleWalk = () => {
@@ -312,13 +344,18 @@ export function createAnimatedRenderer(pack: MascotPack): {
312
344
  const setDragging = (v: boolean) => {
313
345
  setDraggingSignal(v);
314
346
  if (v) {
315
- // 睡着时被拖拽 → 惊醒到 idle,切回 default 帧后手臂 ┃███┃ 才能被扇手渲染匹配
316
347
  if (currentState() === "sleeping") {
317
348
  setState("idle");
318
349
  }
319
350
  setJumpOffset(-1);
351
+ stopDragMsg();
352
+ setDragMsg(DRAG_MSGS[Math.floor(Math.random() * DRAG_MSGS.length)]);
353
+ dragMsgTimer = setInterval(() => {
354
+ setDragMsg(DRAG_MSGS[Math.floor(Math.random() * DRAG_MSGS.length)]);
355
+ }, 800);
320
356
  } else {
321
357
  setJumpOffset(0);
358
+ stopDragMsg();
322
359
  }
323
360
  };
324
361