@linxin666/dsh-pet 0.2.6 → 0.2.8
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/README.i18n.yaml +2 -2
- package/README.md +1 -1
- package/README.zh.md +1 -1
- package/assets/whale/pet.json +54 -54
- package/assets/whale-refined/pet.json +96 -1
- package/lib/client.js +84 -14
- package/lib/client.js.map +1 -1
- package/lib/index.js +62 -58
- package/lib/types/access.js +1 -1
- package/lib/types/affinity.d.ts +18 -18
- package/lib/types/affinity.d.ts.map +1 -1
- package/lib/types/affinity.js +1 -1
- package/lib/types/chatter.d.ts.map +1 -1
- package/lib/types/client/PetDockEntry.js +2 -2
- package/lib/types/client/PetSettingsCard.d.ts.map +1 -1
- package/lib/types/client/PetSettingsCard.js +2 -2
- package/lib/types/client/PetSprite.d.ts.map +1 -1
- package/lib/types/client/PetSprite.js +27 -21
- package/lib/types/client/PluginSettingsCard.d.ts +1 -1
- package/lib/types/client/PluginSettingsCard.d.ts.map +1 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/index.js +56 -9
- package/lib/types/client/locales.d.ts +100 -100
- package/lib/types/client/locales.d.ts.map +1 -1
- package/lib/types/client/renderers/PetRendererSwitch.js +2 -2
- package/lib/types/client/renderers/live2d/Live2dVisualMount.js +2 -2
- package/lib/types/client/renderers/live2d.js +2 -2
- package/lib/types/client/renderers/registry.d.ts.map +1 -1
- package/lib/types/client/settings-form.d.ts.map +1 -1
- package/lib/types/client/spritesheet.js +1 -1
- package/lib/types/client/ui-teardown.d.ts +29 -0
- package/lib/types/client/ui-teardown.d.ts.map +1 -0
- package/lib/types/client/ui-teardown.js +41 -0
- package/lib/types/contracts/status-decoration.d.ts +1 -1
- package/lib/types/decoration.d.ts +1 -1
- package/lib/types/decoration.d.ts.map +1 -1
- package/lib/types/decoration.js +1 -1
- package/lib/types/event-projection.js +1 -1
- package/lib/types/index.js +13 -13
- package/lib/types/invariant.js +2 -2
- package/lib/types/ledger.d.ts.map +1 -1
- package/lib/types/ledger.js +3 -3
- package/lib/types/manifest-v2.d.ts +1 -1
- package/lib/types/manifest-v2.d.ts.map +1 -1
- package/lib/types/model3.js +1 -1
- package/lib/types/persist.js +3 -3
- package/lib/types/registry.d.ts +5 -1
- package/lib/types/registry.d.ts.map +1 -1
- package/lib/types/registry.js +22 -18
- package/lib/types/remarks.d.ts.map +1 -1
- package/lib/types/routes.d.ts.map +1 -1
- package/lib/types/routes.js +4 -4
- package/lib/types/service.d.ts.map +1 -1
- package/lib/types/service.js +7 -7
- package/lib/types/state.d.ts.map +1 -1
- package/lib/types/voice-pack.d.ts +3 -3
- package/lib/types/voice-pack.d.ts.map +1 -1
- package/lib/types/voice-pack.js +1 -1
- package/package.json +12 -9
- package/src/client/PetSprite.test.tsx +168 -26
- package/src/client/PetSprite.tsx +21 -15
- package/src/client/index.test.tsx +118 -11
- package/src/client/index.ts +51 -3
- package/src/client/ui-teardown.ts +47 -0
- package/src/registry.test.ts +14 -0
- package/src/registry.ts +14 -10
package/lib/types/registry.js
CHANGED
|
@@ -30,14 +30,14 @@ import { closeSync, existsSync, openSync, readFileSync, readSync, readdirSync, s
|
|
|
30
30
|
import { homedir } from 'node:os';
|
|
31
31
|
import { basename, dirname, isAbsolute, join, resolve } from 'node:path';
|
|
32
32
|
import { fileURLToPath } from 'node:url';
|
|
33
|
-
import { normalizePetRemarks } from
|
|
34
|
-
import { mergeVoicePacks, normalizeVoicePack } from
|
|
35
|
-
import { parseDecorationManifest } from
|
|
36
|
-
import { imageDimensions } from
|
|
37
|
-
import { PET_DECORATION_API_VERSION } from
|
|
38
|
-
import { dshHome } from
|
|
39
|
-
import { parsePetManifest } from
|
|
40
|
-
import { collectModel3References } from
|
|
33
|
+
import { normalizePetRemarks } from "./remarks.js";
|
|
34
|
+
import { mergeVoicePacks, normalizeVoicePack } from "./voice-pack.js";
|
|
35
|
+
import { parseDecorationManifest } from "./decoration.js";
|
|
36
|
+
import { imageDimensions } from "./image-dimensions.js";
|
|
37
|
+
import { PET_DECORATION_API_VERSION } from "./contracts/status-decoration.js";
|
|
38
|
+
import { dshHome } from "./dsh-home.js";
|
|
39
|
+
import { parsePetManifest } from "./manifest-v2.js";
|
|
40
|
+
import { collectModel3References } from "./model3.js";
|
|
41
41
|
/** Fixed row order of the 9-state animation contract. */
|
|
42
42
|
export const PET_ROW_ORDER = [
|
|
43
43
|
'idle',
|
|
@@ -86,17 +86,21 @@ function assetUrl(prefix, id, file) {
|
|
|
86
86
|
const path = file.split('/').filter(segment => segment !== '').join('/');
|
|
87
87
|
return prefix + '/' + encodeURIComponent(id) + '/' + path;
|
|
88
88
|
}
|
|
89
|
-
/**
|
|
89
|
+
/**
|
|
90
|
+
* Default per-track rhythm — the shared slow baseline every sprite2d pet
|
|
91
|
+
* plays unless its manifest overrides a track (user request: all pets were
|
|
92
|
+
* too fast at the legacy hatch-pet contract pace).
|
|
93
|
+
*/
|
|
90
94
|
export const DEFAULT_TRACK_PATTERNS = {
|
|
91
|
-
idle: { durations: [
|
|
92
|
-
'running-right': { durations: [
|
|
93
|
-
'running-left': { durations: [
|
|
94
|
-
waving: { durations: [
|
|
95
|
-
jumping: { durations: [
|
|
96
|
-
failed: { durations: [
|
|
97
|
-
waiting: { durations: [
|
|
98
|
-
running: { durations: [
|
|
99
|
-
review: { durations: [
|
|
95
|
+
idle: { durations: [500, 500, 600, 500, 500, 600], loop: true },
|
|
96
|
+
'running-right': { durations: [300, 300, 300, 300, 300, 300, 300, 400], loop: true },
|
|
97
|
+
'running-left': { durations: [300, 300, 300, 300, 300, 300, 300, 400], loop: true },
|
|
98
|
+
waving: { durations: [450, 450, 450, 450], loop: true },
|
|
99
|
+
jumping: { durations: [400, 400, 400, 450, 450], loop: false, fallback: 'idle' },
|
|
100
|
+
failed: { durations: [550, 550, 550, 600, 650, 700, 550, 550], loop: false, fallback: 'idle' },
|
|
101
|
+
waiting: { durations: [550, 550, 600, 550, 550, 600], loop: true },
|
|
102
|
+
running: { durations: [330, 330, 330, 330, 330, 400], loop: true },
|
|
103
|
+
review: { durations: [650, 650, 650, 650, 650, 650], loop: true },
|
|
100
104
|
};
|
|
101
105
|
/** Stable id charset: keeps asset URLs plain and filesystem-safe. */
|
|
102
106
|
const PET_ID_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remarks.d.ts","sourceRoot":"","sources":["../../src/remarks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,wDAAwD;AACxD,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,aAAa,GAAG,MAAM,GAAG,cAAc,GAAG,UAAU,CAAA;AAErF,4CAA4C;AAC5C,eAAO,MAAM,YAAY,EAAE,SAAS,UAAU,EAM7C,CAAA;AAED,6EAA6E;AAC7E,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;AAE9D,yEAAyE;AACzE,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC,CAAA;AAE/E,2EAA2E;AAC3E,eAAO,MAAM,eAAe,MAAM,CAAA;AAClC,sCAAsC;AACtC,eAAO,MAAM,gBAAgB,KAAK,CAAA;AAElC;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC,CA2F3E,CAAA;AAED,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAEtD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,OAAO,EACZ,SAAS,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAe,GAC9C,UAAU,GAAG,SAAS,CAyBxB;AAED;;;;GAIG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgC;IACzD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuC;
|
|
1
|
+
{"version":3,"file":"remarks.d.ts","sourceRoot":"","sources":["../../src/remarks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,wDAAwD;AACxD,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,aAAa,GAAG,MAAM,GAAG,cAAc,GAAG,UAAU,CAAA;AAErF,4CAA4C;AAC5C,eAAO,MAAM,YAAY,EAAE,SAAS,UAAU,EAM7C,CAAA;AAED,6EAA6E;AAC7E,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;AAE9D,yEAAyE;AACzE,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC,CAAA;AAE/E,2EAA2E;AAC3E,eAAO,MAAM,eAAe,MAAM,CAAA;AAClC,sCAAsC;AACtC,eAAO,MAAM,gBAAgB,KAAK,CAAA;AAElC;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC,CA2F3E,CAAA;AAED,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAEtD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,OAAO,EACZ,SAAS,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAe,GAC9C,UAAU,GAAG,SAAS,CAyBxB;AAED;;;;GAIG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgC;IACzD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuC;gBAEjD,SAAS,CAAC,EAAE,UAAU;IAQlC,qEAAqE;IACrE,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,MAAM,EAAE;IAIzC,gEAAgE;IAChE,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM;IAO9B,wFAAwF;IACxF,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;CAIhD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAM9C,+CAA+C;AAC/C,eAAO,MAAM,cAAc,aAAa,CAAA;AAExC,0EAA0E;AAC1E,eAAO,MAAM,gBAAgB,SAAS,CAAA;AAMtC;;;;GAIG;AACH,eAAO,MAAM,cAAc;IACzB,yBAAyB
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAM9C,+CAA+C;AAC/C,eAAO,MAAM,cAAc,aAAa,CAAA;AAExC,0EAA0E;AAC1E,eAAO,MAAM,gBAAgB,SAAS,CAAA;AAMtC;;;;GAIG;AACH,eAAO,MAAM,cAAc;IACzB,yBAAyB;;IAEzB,iDAAiD;;IAEjD,8EAA8E;;CAEtE,CAAA;AAEV,6DAA6D;AAC7D,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAWD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAUrF;AAsPD,4EAA4E;AAC5E,eAAO,MAAM,kBAAkB,QAA8B,CAAA;AAe7D,4EAA4E;AAC5E,eAAO,MAAM,eAAe,QAAmB,CAAA;AAE/C,6EAA6E;AAC7E,MAAM,WAAW,eAAe;IAC9B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAwMD,4EAA4E;AAC5E,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,YAAY,CAAA;CAAE,GAAG,eAAe,GAAG,QAAQ,EAAE,CAwDjI;AAGD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA"}
|
package/lib/types/routes.js
CHANGED
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
import { existsSync, realpathSync, statSync } from 'node:fs';
|
|
15
15
|
import { readFile } from 'node:fs/promises';
|
|
16
16
|
import { join, sep } from 'node:path';
|
|
17
|
-
import { DECORATION_ASSET_PREFIX, petEntryView, petPackageRoot } from
|
|
18
|
-
import { isPetAllowed } from
|
|
19
|
-
import { dshHome } from
|
|
17
|
+
import { DECORATION_ASSET_PREFIX, petEntryView, petPackageRoot } from "./registry.js";
|
|
18
|
+
import { isPetAllowed } from "./access.js";
|
|
19
|
+
import { dshHome } from "./dsh-home.js";
|
|
20
20
|
/** Browser-facing base path of the pet API. */
|
|
21
21
|
export const PET_API_PREFIX = '/api/pet';
|
|
22
22
|
/** Browser-facing base path of the pet asset routes ('/pet/<id>/...'). */
|
|
@@ -589,4 +589,4 @@ export function makePetRoutes(deps) {
|
|
|
589
589
|
return [...apiRoutes, assetRoute, runtimeRoute, decorationRoute];
|
|
590
590
|
}
|
|
591
591
|
// Re-exported for the package surface (the registry owns the definition now).
|
|
592
|
-
export { petPackageRoot } from
|
|
592
|
+
export { petPackageRoot } from "./registry.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/service.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/service.ts"],"names":[],"mappings":"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"}
|
package/lib/types/service.js
CHANGED
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
* @module @linxin666/dsh-pet/service
|
|
13
13
|
*/
|
|
14
14
|
import { Service } from '@deepseek-ai/cordis';
|
|
15
|
-
import { emptyProjectionRuntime, isActivityPhase, projectOfficialEvent, } from
|
|
16
|
-
import { PetLedger } from
|
|
17
|
-
import { DEFAULT_PET_NAME, DISPLAY_INSET_MAX, DISPLAY_SIZE_MAX, DISPLAY_SIZE_MIN, PET_NAME_MAX_LENGTH, loadPetPersist, petHomeDir, savePetPersist, } from
|
|
18
|
-
import { DEFAULT_DECORATION_ID, decorationView, loadPetRegistry, petEntryView, petPackageRoot, } from
|
|
19
|
-
import { WHISPER_TTL_MS } from
|
|
20
|
-
import { mergeVoicePacks } from
|
|
21
|
-
import { defaultPetStateConfig, PetStateMachine, } from
|
|
15
|
+
import { emptyProjectionRuntime, isActivityPhase, projectOfficialEvent, } from "./event-projection.js";
|
|
16
|
+
import { PetLedger } from "./ledger.js";
|
|
17
|
+
import { DEFAULT_PET_NAME, DISPLAY_INSET_MAX, DISPLAY_SIZE_MAX, DISPLAY_SIZE_MIN, PET_NAME_MAX_LENGTH, loadPetPersist, petHomeDir, savePetPersist, } from "./persist.js";
|
|
18
|
+
import { DEFAULT_DECORATION_ID, decorationView, loadPetRegistry, petEntryView, petPackageRoot, } from "./registry.js";
|
|
19
|
+
import { WHISPER_TTL_MS } from "./chatter.js";
|
|
20
|
+
import { mergeVoicePacks } from "./voice-pack.js";
|
|
21
|
+
import { defaultPetStateConfig, PetStateMachine, } from "./state.js";
|
|
22
22
|
/** Settings namespace of the pet capability. Spelled here rather than imported: the browser half spells the same value. */
|
|
23
23
|
export const PET_SETTINGS_NAMESPACE = 'pet';
|
|
24
24
|
/** Hard cap on simultaneously displayed session bubbles (most recent first). */
|
package/lib/types/state.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,kDAAkD;AAClD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAA;AAEnG,0EAA0E;AAC1E,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,eAAe,GACf,cAAc,GACd,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,SAAS,GACT,SAAS,GACT,QAAQ,CAAA;AAEZ,kDAAkD;AAClD,MAAM,WAAW,aAAa;IAC5B,oDAAoD;IACpD,KAAK,EAAE,aAAa,CAAA;IACpB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,4DAA4D;AAC5D,MAAM,WAAW,gBAAgB;IAC/B,qCAAqC;IACrC,SAAS,EAAE,YAAY,CAAA;IACvB,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,oEAAoE;IACpE,kBAAkB,EAAE,MAAM,CAAA;IAC1B,oEAAoE;IACpE,KAAK,EAAE,aAAa,CAAA;IACpB,0DAA0D;IAC1D,aAAa,EAAE,OAAO,CAAA;CACvB;AAED,6BAA6B;AAC7B,MAAM,WAAW,cAAc;IAC7B,kFAAkF;IAClF,WAAW,EAAE,MAAM,CAAA;IACnB,yEAAyE;IACzE,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,eAAO,MAAM,qBAAqB,EAAE,cAAuD,CAAA;AAE3F;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,YAAY,CAUpE;AAED,yDAAyD;AACzD,wBAAgB,KAAK,CAAC,SAAS,EAAE,YAAY,GAAG,MAAM,CAarD;AAED;;;GAGG;AACH,qBAAa,eAAe;IAWxB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAVtB,OAAO,CAAC,KAAK,CAAwB;IACrC,OAAO,CAAC,IAAI,CAAoB;IAChC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,kDAAkD;AAClD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAA;AAEnG,0EAA0E;AAC1E,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,eAAe,GACf,cAAc,GACd,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,SAAS,GACT,SAAS,GACT,QAAQ,CAAA;AAEZ,kDAAkD;AAClD,MAAM,WAAW,aAAa;IAC5B,oDAAoD;IACpD,KAAK,EAAE,aAAa,CAAA;IACpB,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,4DAA4D;AAC5D,MAAM,WAAW,gBAAgB;IAC/B,qCAAqC;IACrC,SAAS,EAAE,YAAY,CAAA;IACvB,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,oEAAoE;IACpE,kBAAkB,EAAE,MAAM,CAAA;IAC1B,oEAAoE;IACpE,KAAK,EAAE,aAAa,CAAA;IACpB,0DAA0D;IAC1D,aAAa,EAAE,OAAO,CAAA;CACvB;AAED,6BAA6B;AAC7B,MAAM,WAAW,cAAc;IAC7B,kFAAkF;IAClF,WAAW,EAAE,MAAM,CAAA;IACnB,yEAAyE;IACzE,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,eAAO,MAAM,qBAAqB,EAAE,cAAuD,CAAA;AAE3F;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,YAAY,CAUpE;AAED,yDAAyD;AACzD,wBAAgB,KAAK,CAAC,SAAS,EAAE,YAAY,GAAG,MAAM,CAarD;AAED;;;GAGG;AACH,qBAAa,eAAe;IAWxB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAVtB,OAAO,CAAC,KAAK,CAAwB;IACrC,OAAO,CAAC,IAAI,CAAoB;IAChC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;gBAGrC,MAAM,GAAE,OAAO,CAAC,cAAc,CAAyB,EACtC,GAAG,GAAE,MAAM,MAAiB;IAK/C,6CAA6C;IAC7C,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAQ5C,oEAAoE;IACpE,eAAe,IAAI,IAAI;IAIvB,sDAAsD;IACtD,iBAAiB,IAAI,IAAI;IASzB,6CAA6C;IAC7C,MAAM,IAAI,gBAAgB;CAsB3B"}
|
|
@@ -31,13 +31,13 @@ import { type VoicePackOverrides, type WhisperRule } from './chatter.ts';
|
|
|
31
31
|
/** Schema version this module normalizes (optional field; missing = 1). */
|
|
32
32
|
export declare const VOICE_PACK_V1: 1;
|
|
33
33
|
/** Hover-panel action buttons a pack can show or hide (canonical order). */
|
|
34
|
-
export declare const PANEL_ACTIONS: readonly [
|
|
34
|
+
export declare const PANEL_ACTIONS: readonly ["feed", "rename", "hide"];
|
|
35
35
|
export type PanelAction = (typeof PANEL_ACTIONS)[number];
|
|
36
36
|
/** Panel label slots (unset slots keep the client's i18n dictionary copy). */
|
|
37
|
-
export declare const PANEL_LABEL_KEYS: readonly [
|
|
37
|
+
export declare const PANEL_LABEL_KEYS: readonly ["feed", "rename", "hide", "confirm"];
|
|
38
38
|
export type PanelLabelKey = (typeof PANEL_LABEL_KEYS)[number];
|
|
39
39
|
/** Panel stat slots ({rank}/{n}/{points} interpolate the live values). */
|
|
40
|
-
export declare const PANEL_STAT_KEYS: readonly [
|
|
40
|
+
export declare const PANEL_STAT_KEYS: readonly ["rank", "treats", "points"];
|
|
41
41
|
export type PanelStatKey = (typeof PANEL_STAT_KEYS)[number];
|
|
42
42
|
/** Hover-panel chrome overrides served to the browser half. */
|
|
43
43
|
export interface PetPanelView {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"voice-pack.d.ts","sourceRoot":"","sources":["../../src/voice-pack.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,WAAW,EACjB,MAAM,cAAc,CAAA;AAErB,2EAA2E;AAC3E,eAAO,MAAM,aAAa,EAAG,CAAU,CAAA;AAEvC,4EAA4E;AAC5E,eAAO,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"voice-pack.d.ts","sourceRoot":"","sources":["../../src/voice-pack.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,WAAW,EACjB,MAAM,cAAc,CAAA;AAErB,2EAA2E;AAC3E,eAAO,MAAM,aAAa,EAAG,CAAU,CAAA;AAEvC,4EAA4E;AAC5E,eAAO,MAAM,aAAa,qCAAsC,CAAA;AAChE,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAA;AAExD,8EAA8E;AAC9E,eAAO,MAAM,gBAAgB,gDAAiD,CAAA;AAC9E,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAA;AAE7D,0EAA0E;AAC1E,eAAO,MAAM,eAAe,uCAAwC,CAAA;AACpE,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAA;AAE3D,+DAA+D;AAC/D,MAAM,WAAW,YAAY;IAC3B,wEAAwE;IACxE,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAA;IAC/C,oEAAoE;IACpE,KAAK,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAA;IAC7C,2EAA2E;IAC3E,OAAO,CAAC,EAAE,WAAW,EAAE,CAAA;CACxB;AAED,6EAA6E;AAC7E,MAAM,WAAW,SAAS;IACxB,yEAAyE;IACzE,SAAS,EAAE,kBAAkB,CAAA;IAC7B,sDAAsD;IACtD,KAAK,CAAC,EAAE,YAAY,CAAA;CACrB;AAED,4EAA4E;AAC5E,eAAO,MAAM,oBAAoB,KAAK,CAAA;AACtC,eAAO,MAAM,cAAc,MAAM,CAAA;AACjC,eAAO,MAAM,2BAA2B,KAAK,CAAA;AAC7C,eAAO,MAAM,iBAAiB,KAAK,CAAA;AACnC,eAAO,MAAM,eAAe,KAAK,CAAA;AACjC,eAAO,MAAM,eAAe,KAAK,CAAA;AACjC,eAAO,MAAM,cAAc,KAAK,CAAA;AAYhC,KAAK,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,eAAe,GAAG,gBAAgB,GAAG,aAAa,GAAG,OAAO,GAAG,MAAM,CAAA;AA8B1G;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,QAAQ,EACd,SAAS,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAe,GAC9C,MAAM,EAAE,GAAG,SAAS,CAoBtB;AAED,iFAAiF;AACjF,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,OAAO,EACZ,SAAS,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAe,GAC9C,WAAW,EAAE,GAAG,SAAS,CAyC3B;AAED,2EAA2E;AAC3E,wBAAgB,cAAc,CAC5B,GAAG,EAAE,OAAO,EACZ,SAAS,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAe,GAC9C,YAAY,GAAG,SAAS,CA+D1B;AAED,8FAA8F;AAC9F,eAAO,MAAM,eAAe,aAAoG,CAAA;AAEhI,8DAA8D;AAC9D,eAAO,MAAM,YAAY,aAAgC,CAAA;AAEzD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,OAAO,EACZ,SAAS,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAe,GAC9C,SAAS,GAAG,SAAS,CAmFvB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,MAAM,EAAE,CAAC,SAAS,GAAG,SAAS,CAAC,EAAE,GAAG,SAAS,GAAG,SAAS,CAsC3F"}
|
package/lib/types/voice-pack.js
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* TypeScript mode: keep it erasable-syntax-only.
|
|
28
28
|
* @module @linxin666/dsh-pet/voice-pack
|
|
29
29
|
*/
|
|
30
|
-
import { STATUS_SCENES, TOOL_CATEGORIES, } from
|
|
30
|
+
import { STATUS_SCENES, TOOL_CATEGORIES, } from "./chatter.js";
|
|
31
31
|
/** Schema version this module normalizes (optional field; missing = 1). */
|
|
32
32
|
export const VOICE_PACK_V1 = 1;
|
|
33
33
|
/** Hover-panel action buttons a pack can show or hide (canonical order). */
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@linxin666/dsh-pet",
|
|
3
3
|
"description": "Multi-pet companion plugin for the dsh web GUI: a registry-driven floating pet that reacts to model activity, with per-pet naming, petting/feeding interactions and an affinity score",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.8",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": "^22.19.0 || >=24.0.0"
|
|
@@ -36,6 +36,9 @@
|
|
|
36
36
|
],
|
|
37
37
|
"license": "Apache-2.0",
|
|
38
38
|
"dsh": {
|
|
39
|
+
"engines": {
|
|
40
|
+
"dsh": ">=0.1.1-rc.1"
|
|
41
|
+
},
|
|
39
42
|
"bundle": {
|
|
40
43
|
"patch": "./cordis.patch.yml"
|
|
41
44
|
},
|
|
@@ -59,14 +62,14 @@
|
|
|
59
62
|
},
|
|
60
63
|
"devDependencies": {
|
|
61
64
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
62
|
-
"@deepseek-ai/dsh-client-locale": "^0.1.
|
|
63
|
-
"@deepseek-ai/dsh-client-runtime": "^0.1.
|
|
64
|
-
"@deepseek-ai/dsh-client-ui-conversation": "^0.1.
|
|
65
|
-
"@deepseek-ai/dsh-client-ui-settings": "^0.1.
|
|
66
|
-
"@deepseek-ai/dsh-client-ui-slots": "^0.1.
|
|
67
|
-
"@deepseek-ai/dsh-host-webserver": "^0.1.
|
|
68
|
-
"@deepseek-ai/dsh-session": "^0.1.
|
|
69
|
-
"@deepseek-ai/dsh-settings": "^0.1.
|
|
65
|
+
"@deepseek-ai/dsh-client-locale": "^0.1.1-rc.2",
|
|
66
|
+
"@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2",
|
|
67
|
+
"@deepseek-ai/dsh-client-ui-conversation": "^0.1.1-rc.2",
|
|
68
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.1.1-rc.2",
|
|
69
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.1-rc.2",
|
|
70
|
+
"@deepseek-ai/dsh-host-webserver": "^0.1.1-rc.2",
|
|
71
|
+
"@deepseek-ai/dsh-session": "^0.1.1-rc.2",
|
|
72
|
+
"@deepseek-ai/dsh-settings": "^0.1.1-rc.2",
|
|
70
73
|
"@testing-library/dom": "^10.4.1",
|
|
71
74
|
"@testing-library/react": "^16.3.2",
|
|
72
75
|
"@types/node": "^22.20.0",
|
|
@@ -687,7 +687,7 @@ describe('PetSprite status decoration (pet-center M5, #567)', () => {
|
|
|
687
687
|
expect(ornament()).toBeNull()
|
|
688
688
|
})
|
|
689
689
|
|
|
690
|
-
it('advances the ornament frames on the
|
|
690
|
+
it('advances the ornament frames on the duration timer and wraps when looping', () => {
|
|
691
691
|
vi.spyOn(window, 'matchMedia').mockReturnValue({
|
|
692
692
|
matches: false,
|
|
693
693
|
media: '(prefers-reduced-motion: reduce)',
|
|
@@ -698,7 +698,17 @@ describe('PetSprite status decoration (pet-center M5, #567)', () => {
|
|
|
698
698
|
removeListener: () => {},
|
|
699
699
|
dispatchEvent: () => false,
|
|
700
700
|
})
|
|
701
|
-
|
|
701
|
+
let now = 0
|
|
702
|
+
vi.spyOn(performance, 'now').mockImplementation(() => now)
|
|
703
|
+
// The ornament schedules by frame duration (setTimeout), the sprite
|
|
704
|
+
// still uses rAF; capture both so stepping advances both loops.
|
|
705
|
+
const timers: { at: number; callback: () => void }[] = []
|
|
706
|
+
let timerId = 0
|
|
707
|
+
vi.spyOn(window, 'setTimeout').mockImplementation(((callback: () => void, delay = 0) => {
|
|
708
|
+
timers.push({ at: now + delay, callback })
|
|
709
|
+
return ++timerId
|
|
710
|
+
}) as typeof window.setTimeout)
|
|
711
|
+
vi.spyOn(window, 'clearTimeout').mockImplementation(() => {})
|
|
702
712
|
const frames: FrameRequestCallback[] = []
|
|
703
713
|
vi.spyOn(window, 'requestAnimationFrame').mockImplementation(callback => {
|
|
704
714
|
frames.push(callback)
|
|
@@ -707,18 +717,31 @@ describe('PetSprite status decoration (pet-center M5, #567)', () => {
|
|
|
707
717
|
vi.spyOn(window, 'cancelAnimationFrame').mockImplementation(() => {})
|
|
708
718
|
renderPet({ snapshot: { ...snapshot, bubble: '正在思考', phase: 'thinking', decoration } })
|
|
709
719
|
const el = ornament()!
|
|
710
|
-
//
|
|
711
|
-
//
|
|
712
|
-
|
|
720
|
+
// Run the sprite rAF callbacks immediately (its idle track never moves);
|
|
721
|
+
// run ornament timers as the clock reaches them, repeatedly, because a
|
|
722
|
+
// due timer reschedules the next one at now + duration.
|
|
723
|
+
const step = (ms: number): void => {
|
|
724
|
+
for (const callback of frames.splice(0)) callback(now)
|
|
725
|
+
now += ms
|
|
726
|
+
for (;;) {
|
|
727
|
+
const due = timers.filter(t => t.at <= now)
|
|
728
|
+
if (due.length === 0) break
|
|
729
|
+
for (const t of due) {
|
|
730
|
+
const idx = timers.indexOf(t)
|
|
731
|
+
if (idx >= 0) timers.splice(idx, 1)
|
|
732
|
+
t.callback()
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
}
|
|
713
736
|
// frameWidth = round(64 * 18 / 48) = 24 px; thinking binds frames 0..3.
|
|
714
737
|
expect(el.style.backgroundPosition).toBe('0px 0px')
|
|
715
738
|
act(() => { step(161) })
|
|
716
739
|
expect(el.style.backgroundPosition).toBe('-24px 0px')
|
|
717
|
-
act(() => { step(
|
|
740
|
+
act(() => { step(161) })
|
|
718
741
|
expect(el.style.backgroundPosition).toBe('-48px 0px')
|
|
719
|
-
act(() => { step(
|
|
742
|
+
act(() => { step(161) })
|
|
720
743
|
expect(el.style.backgroundPosition).toBe('-72px 0px')
|
|
721
|
-
act(() => { step(
|
|
744
|
+
act(() => { step(161) })
|
|
722
745
|
// The looping segment wraps back to its first frame.
|
|
723
746
|
expect(el.style.backgroundPosition).toBe('0px 0px')
|
|
724
747
|
})
|
|
@@ -734,7 +757,15 @@ describe('PetSprite status decoration (pet-center M5, #567)', () => {
|
|
|
734
757
|
removeListener: () => {},
|
|
735
758
|
dispatchEvent: () => false,
|
|
736
759
|
})
|
|
737
|
-
|
|
760
|
+
let now = 0
|
|
761
|
+
vi.spyOn(performance, 'now').mockImplementation(() => now)
|
|
762
|
+
const timers: { at: number; callback: () => void }[] = []
|
|
763
|
+
let timerId = 0
|
|
764
|
+
vi.spyOn(window, 'setTimeout').mockImplementation(((callback: () => void, delay = 0) => {
|
|
765
|
+
timers.push({ at: now + delay, callback })
|
|
766
|
+
return ++timerId
|
|
767
|
+
}) as typeof window.setTimeout)
|
|
768
|
+
vi.spyOn(window, 'clearTimeout').mockImplementation(() => {})
|
|
738
769
|
const frames: FrameRequestCallback[] = []
|
|
739
770
|
vi.spyOn(window, 'requestAnimationFrame').mockImplementation(callback => {
|
|
740
771
|
frames.push(callback)
|
|
@@ -743,13 +774,25 @@ describe('PetSprite status decoration (pet-center M5, #567)', () => {
|
|
|
743
774
|
vi.spyOn(window, 'cancelAnimationFrame').mockImplementation(() => {})
|
|
744
775
|
renderPet({ snapshot: { ...snapshot, bubble: '完成', phase: 'done', decoration: { ...decoration, loop: false } } })
|
|
745
776
|
const el = ornament()!
|
|
746
|
-
const step = (
|
|
777
|
+
const step = (ms: number): void => {
|
|
778
|
+
for (const callback of frames.splice(0)) callback(now)
|
|
779
|
+
now += ms
|
|
780
|
+
for (;;) {
|
|
781
|
+
const due = timers.filter(t => t.at <= now)
|
|
782
|
+
if (due.length === 0) break
|
|
783
|
+
for (const t of due) {
|
|
784
|
+
const idx = timers.indexOf(t)
|
|
785
|
+
if (idx >= 0) timers.splice(idx, 1)
|
|
786
|
+
t.callback()
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
}
|
|
747
790
|
// done binds frames 2..3; the segment starts on frame 2.
|
|
748
791
|
expect(el.style.backgroundPosition).toBe('-48px 0px')
|
|
749
792
|
act(() => { step(161) })
|
|
750
793
|
expect(el.style.backgroundPosition).toBe('-72px 0px')
|
|
751
|
-
// The ornament stopped scheduling (only the sprite
|
|
752
|
-
expect(
|
|
794
|
+
// The ornament stopped scheduling timers (only the sprite rAF remains).
|
|
795
|
+
expect(timers).toHaveLength(0)
|
|
753
796
|
act(() => { step(161) })
|
|
754
797
|
// The last frame holds.
|
|
755
798
|
expect(el.style.backgroundPosition).toBe('-72px 0px')
|
|
@@ -767,6 +810,13 @@ describe('PetSprite status decoration (pet-center M5, #567)', () => {
|
|
|
767
810
|
dispatchEvent: () => false,
|
|
768
811
|
})
|
|
769
812
|
vi.spyOn(performance, 'now').mockReturnValue(0)
|
|
813
|
+
const timers: { at: number; callback: () => void }[] = []
|
|
814
|
+
let timerId = 0
|
|
815
|
+
vi.spyOn(window, 'setTimeout').mockImplementation(((callback: () => void, delay = 0) => {
|
|
816
|
+
timers.push({ at: delay, callback })
|
|
817
|
+
return ++timerId
|
|
818
|
+
}) as typeof window.setTimeout)
|
|
819
|
+
vi.spyOn(window, 'clearTimeout').mockImplementation(() => {})
|
|
770
820
|
const frames: FrameRequestCallback[] = []
|
|
771
821
|
vi.spyOn(window, 'requestAnimationFrame').mockImplementation(callback => {
|
|
772
822
|
frames.push(callback)
|
|
@@ -784,15 +834,15 @@ describe('PetSprite status decoration (pet-center M5, #567)', () => {
|
|
|
784
834
|
})
|
|
785
835
|
const el = ornament()!
|
|
786
836
|
// The ornament settles on its only frame, exactly like the reduced-motion
|
|
787
|
-
// hold — no
|
|
837
|
+
// hold — no timer may start (only the sprite's idle rAF is pending).
|
|
788
838
|
expect(el.style.backgroundPosition).toBe('-72px 0px')
|
|
789
|
-
expect(
|
|
839
|
+
expect(timers).toHaveLength(0)
|
|
790
840
|
const step = (ts: number): void => { for (const callback of frames.splice(0)) callback(ts) }
|
|
791
841
|
act(() => { step(161) })
|
|
792
842
|
act(() => { step(322) })
|
|
793
843
|
// The frame never moves and the ornament never reschedules itself.
|
|
794
844
|
expect(el.style.backgroundPosition).toBe('-72px 0px')
|
|
795
|
-
expect(
|
|
845
|
+
expect(timers).toHaveLength(0)
|
|
796
846
|
})
|
|
797
847
|
|
|
798
848
|
it('does not advance the background while a frame is still in play', () => {
|
|
@@ -806,7 +856,15 @@ describe('PetSprite status decoration (pet-center M5, #567)', () => {
|
|
|
806
856
|
removeListener: () => {},
|
|
807
857
|
dispatchEvent: () => false,
|
|
808
858
|
})
|
|
809
|
-
|
|
859
|
+
let now = 0
|
|
860
|
+
vi.spyOn(performance, 'now').mockImplementation(() => now)
|
|
861
|
+
const timers: { at: number; callback: () => void }[] = []
|
|
862
|
+
let timerId = 0
|
|
863
|
+
vi.spyOn(window, 'setTimeout').mockImplementation(((callback: () => void, delay = 0) => {
|
|
864
|
+
timers.push({ at: now + delay, callback })
|
|
865
|
+
return ++timerId
|
|
866
|
+
}) as typeof window.setTimeout)
|
|
867
|
+
vi.spyOn(window, 'clearTimeout').mockImplementation(() => {})
|
|
810
868
|
const frames: FrameRequestCallback[] = []
|
|
811
869
|
vi.spyOn(window, 'requestAnimationFrame').mockImplementation(callback => {
|
|
812
870
|
frames.push(callback)
|
|
@@ -815,7 +873,19 @@ describe('PetSprite status decoration (pet-center M5, #567)', () => {
|
|
|
815
873
|
vi.spyOn(window, 'cancelAnimationFrame').mockImplementation(() => {})
|
|
816
874
|
renderPet({ snapshot: { ...snapshot, bubble: '正在思考', phase: 'thinking', decoration } })
|
|
817
875
|
const el = ornament()!
|
|
818
|
-
const step = (
|
|
876
|
+
const step = (ms: number): void => {
|
|
877
|
+
for (const callback of frames.splice(0)) callback(now)
|
|
878
|
+
now += ms
|
|
879
|
+
for (;;) {
|
|
880
|
+
const due = timers.filter(t => t.at <= now)
|
|
881
|
+
if (due.length === 0) break
|
|
882
|
+
for (const t of due) {
|
|
883
|
+
const idx = timers.indexOf(t)
|
|
884
|
+
if (idx >= 0) timers.splice(idx, 1)
|
|
885
|
+
t.callback()
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
}
|
|
819
889
|
// thinking binds frames 0..3 at 160 ms/frame. The effect holds frame 0;
|
|
820
890
|
// a step at 80 ms — inside the first frame — must not move the ornament,
|
|
821
891
|
// and only crossing the 160 ms boundary advances to the next frame.
|
|
@@ -826,6 +896,58 @@ describe('PetSprite status decoration (pet-center M5, #567)', () => {
|
|
|
826
896
|
expect(el.style.backgroundPosition).toBe('-24px 0px')
|
|
827
897
|
})
|
|
828
898
|
|
|
899
|
+
it('catches up every due frame after a long idle gap', () => {
|
|
900
|
+
vi.spyOn(window, 'matchMedia').mockReturnValue({
|
|
901
|
+
matches: false,
|
|
902
|
+
media: '(prefers-reduced-motion: reduce)',
|
|
903
|
+
onchange: null,
|
|
904
|
+
addEventListener: () => {},
|
|
905
|
+
removeEventListener: () => {},
|
|
906
|
+
addListener: () => {},
|
|
907
|
+
removeListener: () => {},
|
|
908
|
+
dispatchEvent: () => false,
|
|
909
|
+
})
|
|
910
|
+
let now = 0
|
|
911
|
+
vi.spyOn(performance, 'now').mockImplementation(() => now)
|
|
912
|
+
const timers: { at: number; callback: () => void }[] = []
|
|
913
|
+
let timerId = 0
|
|
914
|
+
vi.spyOn(window, 'setTimeout').mockImplementation(((callback: () => void, delay = 0) => {
|
|
915
|
+
timers.push({ at: now + delay, callback })
|
|
916
|
+
return ++timerId
|
|
917
|
+
}) as typeof window.setTimeout)
|
|
918
|
+
vi.spyOn(window, 'clearTimeout').mockImplementation(() => {})
|
|
919
|
+
const frames: FrameRequestCallback[] = []
|
|
920
|
+
vi.spyOn(window, 'requestAnimationFrame').mockImplementation(callback => {
|
|
921
|
+
frames.push(callback)
|
|
922
|
+
return frames.length
|
|
923
|
+
})
|
|
924
|
+
vi.spyOn(window, 'cancelAnimationFrame').mockImplementation(() => {})
|
|
925
|
+
renderPet({ snapshot: { ...snapshot, bubble: '正在思考', phase: 'thinking', decoration } })
|
|
926
|
+
const el = ornament()!
|
|
927
|
+
const step = (ms: number): void => {
|
|
928
|
+
for (const callback of frames.splice(0)) callback(now)
|
|
929
|
+
now += ms
|
|
930
|
+
for (;;) {
|
|
931
|
+
const due = timers.filter(t => t.at <= now)
|
|
932
|
+
if (due.length === 0) break
|
|
933
|
+
for (const t of due) {
|
|
934
|
+
const idx = timers.indexOf(t)
|
|
935
|
+
if (idx >= 0) timers.splice(idx, 1)
|
|
936
|
+
t.callback()
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
// A 500 ms gap (jank / background tab) spans three 160 ms frames; the
|
|
941
|
+
// ornament must advance through all of them (0 -> 1 -> 2 -> 3), not
|
|
942
|
+
// drop the surplus time.
|
|
943
|
+
expect(el.style.backgroundPosition).toBe('0px 0px')
|
|
944
|
+
act(() => { step(500) })
|
|
945
|
+
expect(el.style.backgroundPosition).toBe('-72px 0px')
|
|
946
|
+
act(() => { step(161) })
|
|
947
|
+
// The next frame tick wraps the looping segment back to its first frame.
|
|
948
|
+
expect(el.style.backgroundPosition).toBe('0px 0px')
|
|
949
|
+
})
|
|
950
|
+
|
|
829
951
|
it('does not restart the frame loop when an equal-content decoration re-renders', () => {
|
|
830
952
|
vi.spyOn(window, 'matchMedia').mockReturnValue({
|
|
831
953
|
matches: false,
|
|
@@ -837,21 +959,41 @@ describe('PetSprite status decoration (pet-center M5, #567)', () => {
|
|
|
837
959
|
removeListener: () => {},
|
|
838
960
|
dispatchEvent: () => false,
|
|
839
961
|
})
|
|
840
|
-
|
|
962
|
+
let now = 0
|
|
963
|
+
vi.spyOn(performance, 'now').mockImplementation(() => now)
|
|
964
|
+
const timers: { at: number; callback: () => void }[] = []
|
|
965
|
+
let timerId = 0
|
|
966
|
+
const timerSpy = vi.spyOn(window, 'setTimeout').mockImplementation(((callback: () => void, delay = 0) => {
|
|
967
|
+
timers.push({ at: now + delay, callback })
|
|
968
|
+
return ++timerId
|
|
969
|
+
}) as typeof window.setTimeout)
|
|
970
|
+
const clearSpy = vi.spyOn(window, 'clearTimeout').mockImplementation(() => {})
|
|
841
971
|
const frames: FrameRequestCallback[] = []
|
|
842
|
-
|
|
972
|
+
vi.spyOn(window, 'requestAnimationFrame').mockImplementation(callback => {
|
|
843
973
|
frames.push(callback)
|
|
844
974
|
return frames.length
|
|
845
975
|
})
|
|
846
|
-
|
|
976
|
+
vi.spyOn(window, 'cancelAnimationFrame').mockImplementation(() => {})
|
|
847
977
|
// The definition comes from '/api/pet/pets', fetched once — a state
|
|
848
978
|
// poll never replaces it, so both renders share one definition object.
|
|
849
979
|
const definition = petDefinition()
|
|
850
980
|
const { result } = renderPet({ definition, snapshot: { ...snapshot, bubble: '正在思考', phase: 'thinking', decoration } })
|
|
851
|
-
const step = (
|
|
981
|
+
const step = (ms: number): void => {
|
|
982
|
+
for (const callback of frames.splice(0)) callback(now)
|
|
983
|
+
now += ms
|
|
984
|
+
for (;;) {
|
|
985
|
+
const due = timers.filter(t => t.at <= now)
|
|
986
|
+
if (due.length === 0) break
|
|
987
|
+
for (const t of due) {
|
|
988
|
+
const idx = timers.indexOf(t)
|
|
989
|
+
if (idx >= 0) timers.splice(idx, 1)
|
|
990
|
+
t.callback()
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
}
|
|
852
994
|
act(() => { step(161) })
|
|
853
995
|
expect(ornament()!.style.backgroundPosition).toBe('-24px 0px')
|
|
854
|
-
const schedulesBefore =
|
|
996
|
+
const schedulesBefore = timerSpy.mock.calls.length
|
|
855
997
|
// The 2 s poll delivers a fresh JSON round-trip: identical content, new
|
|
856
998
|
// object identities everywhere. The loop must not cancel/restart.
|
|
857
999
|
const repolled: DecorationView = {
|
|
@@ -861,10 +1003,10 @@ describe('PetSprite status decoration (pet-center M5, #567)', () => {
|
|
|
861
1003
|
phases: { ...decoration.phases },
|
|
862
1004
|
}
|
|
863
1005
|
result.rerender(<PetSprite {...petProps({ definition, snapshot: { ...snapshot, bubble: '正在思考', phase: 'thinking', decoration: repolled } })} />)
|
|
864
|
-
act(() => { step(
|
|
1006
|
+
act(() => { step(161) })
|
|
865
1007
|
expect(ornament()!.style.backgroundPosition).toBe('-48px 0px')
|
|
866
|
-
expect(
|
|
867
|
-
// One reschedule per
|
|
868
|
-
expect(
|
|
1008
|
+
expect(clearSpy).not.toHaveBeenCalled()
|
|
1009
|
+
// One reschedule per frame tick; no effect restart added new timers.
|
|
1010
|
+
expect(timerSpy.mock.calls.length).toBe(schedulesBefore + 1)
|
|
869
1011
|
})
|
|
870
1012
|
})
|
package/src/client/PetSprite.tsx
CHANGED
|
@@ -98,32 +98,38 @@ function StatusOrnament(props: { decoration: DecorationView; phase: ActivityPhas
|
|
|
98
98
|
// tick would keep rescheduling a no-op rAF forever. Settle on the one
|
|
99
99
|
// frame instead — same as the reduced-motion static hold.
|
|
100
100
|
if (reduceMotion || segment.from === segment.to) return
|
|
101
|
-
let
|
|
101
|
+
let timer = 0
|
|
102
102
|
let index = segment.from
|
|
103
103
|
let elapsed = 0
|
|
104
104
|
let last = performance.now()
|
|
105
|
-
const tick = (
|
|
106
|
-
const
|
|
107
|
-
|
|
105
|
+
const tick = (): void => {
|
|
106
|
+
const now = performance.now()
|
|
107
|
+
const delta = now - last
|
|
108
|
+
last = now
|
|
108
109
|
elapsed += delta
|
|
109
|
-
const duration = decoration.durations[index] ??
|
|
110
|
+
const duration = decoration.durations[index] ?? 120
|
|
111
|
+
// The segment's frame rate (duration ms, typically 90-160) is far
|
|
112
|
+
// below the rAF cadence, so a 60fps loop would spend ~90% of its
|
|
113
|
+
// ticks doing nothing. Schedule by the remaining time to the next
|
|
114
|
+
// frame instead — the ornament wakes once per frame, not once per
|
|
115
|
+
// screen refresh. A late wake (background tab, jank) carries extra
|
|
116
|
+
// elapsed time, so catch up every due frame like the sprite loop.
|
|
110
117
|
if (elapsed >= duration) {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
//
|
|
117
|
-
// would churn style recalculations for no visual change.
|
|
118
|
+
do {
|
|
119
|
+
elapsed -= duration
|
|
120
|
+
if (index < segment.to) index += 1
|
|
121
|
+
else if (decoration.loop) index = segment.from
|
|
122
|
+
} while (elapsed >= duration)
|
|
123
|
+
// Only advance the background when the frame actually changes.
|
|
118
124
|
el.style.backgroundPosition = position(index)
|
|
119
125
|
}
|
|
120
126
|
// A non-looping segment settles on its last frame; stop scheduling
|
|
121
127
|
// instead of repainting the same position every frame.
|
|
122
128
|
if (!decoration.loop && index === segment.to) return
|
|
123
|
-
|
|
129
|
+
timer = window.setTimeout(tick, Math.max(1, duration - elapsed))
|
|
124
130
|
}
|
|
125
|
-
|
|
126
|
-
return () =>
|
|
131
|
+
timer = window.setTimeout(tick, 0)
|
|
132
|
+
return () => window.clearTimeout(timer)
|
|
127
133
|
}, [shown, segmentKey, frameWidth, decoration.loop, durationsKey])
|
|
128
134
|
if (!shown) return null
|
|
129
135
|
return (
|