@mingxy/opencode-mascot 0.2.3 → 0.2.5
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
|
@@ -200,12 +200,5 @@ export const yueerPack: MascotPack = {
|
|
|
200
200
|
idleTimeout: 90000,
|
|
201
201
|
},
|
|
202
202
|
|
|
203
|
-
sidebar: {
|
|
204
|
-
greetings: ["师尊,月儿在此候命~"],
|
|
205
|
-
busyPhrases: ["铸造法器中..."],
|
|
206
|
-
},
|
|
207
|
-
|
|
208
|
-
bubbleTexts: ["嗯...", "让我想想...", "等等...", "本帝在算..."],
|
|
209
|
-
|
|
210
203
|
effects: yueerEffects,
|
|
211
204
|
};
|
|
@@ -2,14 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
import { createSignal } from "solid-js";
|
|
4
4
|
import type { JSX } from "@opentui/solid";
|
|
5
|
-
import type { MascotPack, MascotState
|
|
5
|
+
import type { MascotPack, MascotState } from "../core/types";
|
|
6
6
|
import { createAnimatedRenderer } from "../core/ascii-renderer";
|
|
7
7
|
import { onCelebrate } from "../core/celebration-bus";
|
|
8
8
|
import { useDraggableMascot } from "./use-draggable-mascot";
|
|
9
9
|
|
|
10
10
|
interface SidebarMascotProps {
|
|
11
11
|
mascots: Record<string, MascotPack>;
|
|
12
|
-
switchConfig?: SwitchConfig;
|
|
13
12
|
initialMascot?: string;
|
|
14
13
|
api: {
|
|
15
14
|
event: {
|
|
@@ -73,7 +72,7 @@ export function SidebarMascot(props: SidebarMascotProps): JSX.Element {
|
|
|
73
72
|
const cur = currentName();
|
|
74
73
|
renderers[cur].setState(s);
|
|
75
74
|
|
|
76
|
-
const stateMap =
|
|
75
|
+
const stateMap = DEFAULT_STATE_MAP;
|
|
77
76
|
const target = stateMap[s];
|
|
78
77
|
if (target && target !== cur && props.mascots[target]) {
|
|
79
78
|
setCurrentName(target);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/** @jsxImportSource @opentui/solid */
|
|
2
2
|
|
|
3
3
|
import { createSignal, onCleanup, type Accessor } from "solid-js";
|
|
4
|
-
import { useTerminalDimensions } from "@opentui/solid";
|
|
5
4
|
|
|
6
5
|
type DragState = "normal" | "edge_hidden" | "returning";
|
|
7
6
|
type HideSide = "left" | "right" | null;
|
|
@@ -26,6 +25,12 @@ interface UseDraggableOpts {
|
|
|
26
25
|
enableEdge?: boolean;
|
|
27
26
|
}
|
|
28
27
|
|
|
28
|
+
function getTermSize(): { width: number; height: number } {
|
|
29
|
+
const width = (typeof process !== "undefined" && process.stdout?.columns) || 80;
|
|
30
|
+
const height = (typeof process !== "undefined" && process.stdout?.rows) || 24;
|
|
31
|
+
return { width, height };
|
|
32
|
+
}
|
|
33
|
+
|
|
29
34
|
export function useDraggableMascot(opts: UseDraggableOpts): {
|
|
30
35
|
posX: Accessor<number>;
|
|
31
36
|
posY: Accessor<number>;
|
|
@@ -38,7 +43,6 @@ export function useDraggableMascot(opts: UseDraggableOpts): {
|
|
|
38
43
|
|
|
39
44
|
const [posX, setPosX] = createSignal(opts.initialX);
|
|
40
45
|
const [posY, setPosY] = createSignal(opts.initialY);
|
|
41
|
-
const dims = useTerminalDimensions();
|
|
42
46
|
|
|
43
47
|
let dragStartX = 0;
|
|
44
48
|
let dragStartY = 0;
|
|
@@ -62,7 +66,7 @@ export function useDraggableMascot(opts: UseDraggableOpts): {
|
|
|
62
66
|
|
|
63
67
|
const clampX = (rawX: number): number => {
|
|
64
68
|
if (!enableEdge) return rawX;
|
|
65
|
-
const { width } =
|
|
69
|
+
const { width } = getTermSize();
|
|
66
70
|
const minX = -(opts.mascotWidth - peek);
|
|
67
71
|
const maxX = width - peek;
|
|
68
72
|
return Math.max(minX, Math.min(rawX, maxX));
|
|
@@ -70,7 +74,7 @@ export function useDraggableMascot(opts: UseDraggableOpts): {
|
|
|
70
74
|
|
|
71
75
|
const clampY = (rawY: number): number => {
|
|
72
76
|
if (!enableEdge) return rawY;
|
|
73
|
-
const { height } =
|
|
77
|
+
const { height } = getTermSize();
|
|
74
78
|
return Math.max(0, Math.min(rawY, height - opts.mascotHeight));
|
|
75
79
|
};
|
|
76
80
|
|
|
@@ -81,7 +85,7 @@ export function useDraggableMascot(opts: UseDraggableOpts): {
|
|
|
81
85
|
peekTimer = setInterval(() => {
|
|
82
86
|
phase = !phase;
|
|
83
87
|
const stretch = phase ? 2 : 0;
|
|
84
|
-
const { width } =
|
|
88
|
+
const { width } = getTermSize();
|
|
85
89
|
if (hideSide === "left") {
|
|
86
90
|
setPosX(-(opts.mascotWidth - peek) + stretch);
|
|
87
91
|
} else if (hideSide === "right") {
|
|
@@ -94,7 +98,7 @@ export function useDraggableMascot(opts: UseDraggableOpts): {
|
|
|
94
98
|
if (state !== "edge_hidden") return;
|
|
95
99
|
stopPeek();
|
|
96
100
|
state = "returning";
|
|
97
|
-
const { width } =
|
|
101
|
+
const { width } = getTermSize();
|
|
98
102
|
const cur = posX();
|
|
99
103
|
const targetX = hideSide === "left" ? 0 : Math.max(0, width - opts.mascotWidth);
|
|
100
104
|
const step = targetX > cur ? 2 : -2;
|
|
@@ -115,7 +119,7 @@ export function useDraggableMascot(opts: UseDraggableOpts): {
|
|
|
115
119
|
|
|
116
120
|
const checkEdgeOnRelease = () => {
|
|
117
121
|
if (!enableEdge) return;
|
|
118
|
-
const { width } =
|
|
122
|
+
const { width } = getTermSize();
|
|
119
123
|
const x = posX();
|
|
120
124
|
if (x <= -(opts.mascotWidth - peek) + 1) {
|
|
121
125
|
hideSide = "left";
|
|
@@ -269,8 +269,8 @@ export function createAnimatedRenderer(pack: MascotPack): {
|
|
|
269
269
|
|
|
270
270
|
return (
|
|
271
271
|
<box flexDirection="column" left={left} top={top}>
|
|
272
|
-
{renderLines(lines, fg)}
|
|
273
272
|
{cel ? <text fg={fg}>{cel.text}</text> : null}
|
|
273
|
+
{renderLines(lines, fg)}
|
|
274
274
|
</box>
|
|
275
275
|
);
|
|
276
276
|
};
|
|
@@ -314,8 +314,9 @@ export function createAnimatedRenderer(pack: MascotPack): {
|
|
|
314
314
|
|
|
315
315
|
// 连续跳跃 + 吐火星文泡泡庆祝更新成功
|
|
316
316
|
const celebrateUpdate = (newVersion: string) => {
|
|
317
|
-
const bubbles =
|
|
318
|
-
|
|
317
|
+
const bubbles = ["ᵘᵖ~", "ⁿᵉʷ!", "ʸᵉ~", "ᵍᵒ~", "ᵒᵏ~"];
|
|
318
|
+
setState("happy");
|
|
319
|
+
setFrameOverride("happy");
|
|
319
320
|
|
|
320
321
|
let step = 0;
|
|
321
322
|
const JUMPS = 3;
|
|
@@ -323,6 +324,8 @@ export function createAnimatedRenderer(pack: MascotPack): {
|
|
|
323
324
|
if (step >= JUMPS) {
|
|
324
325
|
setJumpOffset(0);
|
|
325
326
|
setCelebrate(null);
|
|
327
|
+
setFrameOverride(null);
|
|
328
|
+
setState("idle");
|
|
326
329
|
return;
|
|
327
330
|
}
|
|
328
331
|
setJumpOffset(step % 2 === 0 ? -2 : 0);
|
package/src/core/types.ts
CHANGED
|
@@ -25,14 +25,6 @@ export interface AnimationConfig {
|
|
|
25
25
|
jumpMaxDelay?: number;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
/**
|
|
29
|
-
* Sidebar display configuration.
|
|
30
|
-
*/
|
|
31
|
-
export interface SidebarConfig {
|
|
32
|
-
greetings?: string[];
|
|
33
|
-
busyPhrases?: string[];
|
|
34
|
-
}
|
|
35
|
-
|
|
36
28
|
// ─── Effect system types ───
|
|
37
29
|
|
|
38
30
|
/**
|
|
@@ -130,25 +122,7 @@ export interface MascotPack {
|
|
|
130
122
|
};
|
|
131
123
|
|
|
132
124
|
animations?: AnimationConfig;
|
|
133
|
-
sidebar?: SidebarConfig;
|
|
134
125
|
|
|
135
126
|
/** Mascot-specific animation effects (timers + render) */
|
|
136
127
|
effects?: MascotEffects;
|
|
137
|
-
|
|
138
|
-
/** Thinking bubble phrases, shown when mascot is in busy/thinking state */
|
|
139
|
-
bubbleTexts?: string[];
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
export interface SwitchConfig {
|
|
143
|
-
onState?: Partial<Record<MascotState, string>>;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* User-facing configuration merged from opencode config file.
|
|
148
|
-
*/
|
|
149
|
-
export interface MascotConfig {
|
|
150
|
-
mascot: string;
|
|
151
|
-
animations: boolean;
|
|
152
|
-
idleSleep: boolean;
|
|
153
|
-
switchConfig?: SwitchConfig;
|
|
154
128
|
}
|