@lemoncat7/dsh-theme-xiaohei 0.4.5 → 0.5.0
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.md +25 -92
- package/THIRD_PARTY_NOTICES.md +13 -1
- package/docs/dsh-021-compatibility.md +23 -0
- package/docs/releases/0.4.6.md +17 -0
- package/docs/releases/0.5.0.md +24 -0
- package/docs/releases/README.md +14 -0
- package/docs/rift-interaction.md +35 -0
- package/docs/rift-preview.md +39 -0
- package/lib/client.companion.js +99 -0
- package/lib/client.decorations.js +224 -51
- package/lib/client.js +532 -2501
- package/lib/index.d.ts +1 -2
- package/lib/index.js +393 -11
- package/lib/rift/boot.d.ts +6 -0
- package/package.json +30 -19
- package/lib/appearance.d.ts +0 -12
- package/lib/appearance.js +0 -42
- package/lib/blink.d.ts +0 -4
- package/lib/blink.js +0 -110
- package/lib/bloub-heixiu/ambient.d.ts +0 -3
- package/lib/bloub-heixiu/ambient.js +0 -12
- package/lib/bloub-heixiu/character.d.ts +0 -33
- package/lib/bloub-heixiu/character.js +0 -124
- package/lib/bloub-heixiu/effects.d.ts +0 -4
- package/lib/bloub-heixiu/effects.js +0 -91
- package/lib/bloub-heixiu/flight.d.ts +0 -15
- package/lib/bloub-heixiu/flight.js +0 -66
- package/lib/bloub-heixiu/follow.d.ts +0 -13
- package/lib/bloub-heixiu/follow.js +0 -23
- package/lib/bloub-heixiu/layout.d.ts +0 -18
- package/lib/bloub-heixiu/layout.js +0 -12
- package/lib/bloub-heixiu/renderer.d.ts +0 -16
- package/lib/bloub-heixiu/renderer.js +0 -94
- package/lib/bloub-heixiu/runtime.d.ts +0 -6
- package/lib/bloub-heixiu/runtime.js +0 -409
- package/lib/bloub-heixiu/signals.d.ts +0 -17
- package/lib/bloub-heixiu/signals.js +0 -55
- package/lib/bloub-heixiu/styles.d.ts +0 -2
- package/lib/bloub-heixiu/styles.js +0 -98
- package/lib/boot-appearance.d.ts +0 -10
- package/lib/boot-appearance.js +0 -47
- package/lib/boot-loader.d.ts +0 -5
- package/lib/boot-loader.js +0 -158
- package/lib/chrome/accessibility.d.ts +0 -3
- package/lib/chrome/accessibility.js +0 -69
- package/lib/chrome/blink.d.ts +0 -3
- package/lib/chrome/blink.js +0 -15
- package/lib/chrome/composer-avatar.d.ts +0 -10
- package/lib/chrome/composer-avatar.js +0 -599
- package/lib/chrome/composer-send-heixiu.d.ts +0 -3
- package/lib/chrome/composer-send-heixiu.js +0 -143
- package/lib/chrome/composer.d.ts +0 -3
- package/lib/chrome/composer.js +0 -135
- package/lib/chrome/controls.d.ts +0 -8
- package/lib/chrome/controls.js +0 -348
- package/lib/chrome/conversation-messages.d.ts +0 -3
- package/lib/chrome/conversation-messages.js +0 -329
- package/lib/chrome/conversation-submissions.d.ts +0 -3
- package/lib/chrome/conversation-submissions.js +0 -68
- package/lib/chrome/conversation.d.ts +0 -3
- package/lib/chrome/conversation.js +0 -67
- package/lib/chrome/frames.d.ts +0 -6
- package/lib/chrome/frames.js +0 -134
- package/lib/chrome/gaze.d.ts +0 -3
- package/lib/chrome/gaze.js +0 -103
- package/lib/chrome/identity.d.ts +0 -6
- package/lib/chrome/identity.js +0 -47
- package/lib/chrome/overlays.d.ts +0 -3
- package/lib/chrome/overlays.js +0 -104
- package/lib/chrome/portal.d.ts +0 -6
- package/lib/chrome/portal.js +0 -169
- package/lib/chrome/reactions.d.ts +0 -3
- package/lib/chrome/reactions.js +0 -85
- package/lib/chrome/sidebar.d.ts +0 -3
- package/lib/chrome/sidebar.js +0 -313
- package/lib/chrome/tokens.d.ts +0 -3
- package/lib/chrome/tokens.js +0 -224
- package/lib/chrome/workspace.d.ts +0 -3
- package/lib/chrome/workspace.js +0 -94
- package/lib/chrome.d.ts +0 -10
- package/lib/chrome.js +0 -46
- package/lib/client-entry.d.ts +0 -3
- package/lib/client-entry.js +0 -3
- package/lib/client.d.ts +0 -10
- package/lib/client.pose-chin-dark.js +0 -4
- package/lib/client.pose-chin-light.js +0 -4
- package/lib/client.pose-doze-dark.js +0 -4
- package/lib/client.pose-doze-light.js +0 -4
- package/lib/client.pose-halfpeek-dark.js +0 -4
- package/lib/client.pose-halfpeek-light.js +0 -4
- package/lib/client.pose-peek-dark.js +0 -4
- package/lib/client.pose-peek-light.js +0 -4
- package/lib/client.pose-seated-dark.js +0 -4
- package/lib/client.pose-seated-light.js +0 -4
- package/lib/client.rig-chin-dark.js +0 -4
- package/lib/client.rig-chin-light.js +0 -4
- package/lib/client.rig-halfpeek-dark.js +0 -4
- package/lib/client.rig-halfpeek-light.js +0 -4
- package/lib/client.rig-peek-dark.js +0 -4
- package/lib/client.rig-peek-light.js +0 -4
- package/lib/client.rig-seated-dark.js +0 -4
- package/lib/client.rig-seated-light.js +0 -4
- package/lib/composer-avatar.d.ts +0 -18
- package/lib/composer-avatar.js +0 -441
- package/lib/composer-draft-preview.d.ts +0 -4
- package/lib/composer-draft-preview.js +0 -8
- package/lib/composer-send-heixiu.d.ts +0 -8
- package/lib/composer-send-heixiu.js +0 -133
- package/lib/current-session.d.ts +0 -6
- package/lib/current-session.js +0 -5
- package/lib/decorations-entry.d.ts +0 -3
- package/lib/decorations-entry.js +0 -18
- package/lib/deferred-decorations.d.ts +0 -3
- package/lib/deferred-decorations.js +0 -51
- package/lib/gaze.d.ts +0 -4
- package/lib/gaze.js +0 -230
- package/lib/generated-backgrounds.d.ts +0 -14
- package/lib/generated-backgrounds.js +0 -14
- package/lib/generated-character-motion.d.ts +0 -4
- package/lib/generated-character-motion.js +0 -2
- package/lib/generated-identity.d.ts +0 -6
- package/lib/generated-identity.js +0 -6
- package/lib/generated-keyart.d.ts +0 -34
- package/lib/generated-keyart.js +0 -34
- package/lib/generated-loading-assets.d.ts +0 -4
- package/lib/generated-loading-assets.js +0 -4
- package/lib/heixiu-interactions.d.ts +0 -10
- package/lib/heixiu-interactions.js +0 -161
- package/lib/host-contract.d.ts +0 -9
- package/lib/host-contract.js +0 -13
- package/lib/host-dom.d.ts +0 -11
- package/lib/host-dom.js +0 -68
- package/lib/loading-heixiu.d.ts +0 -8
- package/lib/loading-heixiu.js +0 -287
- package/lib/metallic-brand-mark.d.ts +0 -10
- package/lib/metallic-brand-mark.js +0 -296
- package/lib/plugin.d.ts +0 -6
- package/lib/plugin.js +0 -60
- package/lib/portal.d.ts +0 -40
- package/lib/portal.js +0 -225
- package/lib/reactions.d.ts +0 -20
- package/lib/reactions.js +0 -380
- package/lib/scene/avatar-model.d.ts +0 -6
- package/lib/scene/avatar-model.js +0 -646
- package/lib/scene/avatar-motion.d.ts +0 -3
- package/lib/scene/avatar-motion.js +0 -799
- package/lib/scene/character-assets.d.ts +0 -13
- package/lib/scene/character-assets.js +0 -26
- package/lib/scene/character-expression.d.ts +0 -4
- package/lib/scene/character-expression.js +0 -15
- package/lib/scene/character-eye-material.d.ts +0 -13
- package/lib/scene/character-eye-material.js +0 -88
- package/lib/scene/character-eye-renderer.d.ts +0 -5
- package/lib/scene/character-eye-renderer.js +0 -80
- package/lib/scene/character-eye-rig.d.ts +0 -20
- package/lib/scene/character-eye-rig.js +0 -35
- package/lib/scene/character-gaze.d.ts +0 -16
- package/lib/scene/character-gaze.js +0 -36
- package/lib/scene/character-idle.d.ts +0 -17
- package/lib/scene/character-idle.js +0 -65
- package/lib/scene/character-layout.d.ts +0 -24
- package/lib/scene/character-layout.js +0 -51
- package/lib/scene/character-motion-clock.d.ts +0 -18
- package/lib/scene/character-motion-clock.js +0 -70
- package/lib/scene/character-motion-types.d.ts +0 -12
- package/lib/scene/character-motion-types.js +0 -2
- package/lib/scene/character-motion.d.ts +0 -6
- package/lib/scene/character-motion.js +0 -187
- package/lib/scene/character-poses.d.ts +0 -26
- package/lib/scene/character-poses.js +0 -11
- package/lib/scene/character-rig-renderer.d.ts +0 -5
- package/lib/scene/character-rig-renderer.js +0 -95
- package/lib/scene/character-rig.d.ts +0 -22
- package/lib/scene/character-rig.js +0 -61
- package/lib/scene/heixiu-feedback.d.ts +0 -3
- package/lib/scene/heixiu-feedback.js +0 -64
- package/lib/scene/heixiu-interactions.d.ts +0 -3
- package/lib/scene/heixiu-interactions.js +0 -92
- package/lib/scene/ids.d.ts +0 -5
- package/lib/scene/ids.js +0 -5
- package/lib/scene/pointer-bridge.d.ts +0 -21
- package/lib/scene/pointer-bridge.js +0 -155
- package/lib/scene/runtime.d.ts +0 -12
- package/lib/scene/runtime.js +0 -74
- package/lib/scene/state-transitions.d.ts +0 -3
- package/lib/scene/state-transitions.js +0 -37
- package/lib/scene/styles.d.ts +0 -5
- package/lib/scene/styles.js +0 -69
- package/lib/scene/sylva-performance.d.ts +0 -11
- package/lib/scene/sylva-performance.js +0 -58
- package/lib/scene/wallpaper-character-styles.d.ts +0 -3
- package/lib/scene/wallpaper-character-styles.js +0 -49
- package/lib/scene/wallpaper-character.d.ts +0 -5
- package/lib/scene/wallpaper-character.js +0 -222
- package/lib/scene.d.ts +0 -8
- package/lib/scene.js +0 -8
- package/lib/sidebar-glass.d.ts +0 -16
- package/lib/sidebar-glass.js +0 -168
- package/lib/sidebar-heixiu-escape.d.ts +0 -44
- package/lib/sidebar-heixiu-escape.js +0 -340
- package/lib/sidebar-heixiu-roaming.d.ts +0 -27
- package/lib/sidebar-heixiu-roaming.js +0 -310
- package/lib/sidebar-reveal.d.ts +0 -8
- package/lib/sidebar-reveal.js +0 -59
- package/lib/state.d.ts +0 -21
- package/lib/state.js +0 -123
- package/lib/theme.d.ts +0 -19
- package/lib/theme.js +0 -188
- package/lib/vendor/bloub/decor.d.ts +0 -114
- package/lib/vendor/bloub/decor.js +0 -198
- package/lib/vendor/bloub/engine.d.ts +0 -213
- package/lib/vendor/bloub/engine.js +0 -452
- package/lib/vendor/bloub/expressions.d.ts +0 -35
- package/lib/vendor/bloub/expressions.js +0 -143
- package/lib/vendor/bloub/eyefit.d.ts +0 -75
- package/lib/vendor/bloub/eyefit.js +0 -393
- package/lib/vendor/bloub/face.d.ts +0 -63
- package/lib/vendor/bloub/face.js +0 -106
- package/lib/vendor/bloub/math.d.ts +0 -22
- package/lib/vendor/bloub/math.js +0 -36
- package/lib/vendor/bloub/profiles.d.ts +0 -8
- package/lib/vendor/bloub/profiles.js +0 -20
- package/lib/vendor/bloub/repere.d.ts +0 -30
- package/lib/vendor/bloub/repere.js +0 -32
- package/lib/vendor/bloub/shape.d.ts +0 -80
- package/lib/vendor/bloub/shape.js +0 -268
- package/lib/vendor/bloub/skins.d.ts +0 -36
- package/lib/vendor/bloub/skins.js +0 -74
- package/lib/vendor/bloub/states.d.ts +0 -87
- package/lib/vendor/bloub/states.js +0 -468
package/lib/composer-avatar.js
DELETED
|
@@ -1,441 +0,0 @@
|
|
|
1
|
-
import { XIAOHEI_BREAKFRAME_BLINK, XIAOHEI_BREAKFRAME_BRACE, XIAOHEI_BREAKFRAME_COMPLETE, XIAOHEI_BREAKFRAME_ERROR, XIAOHEI_BREAKFRAME_IDLE, XIAOHEI_BREAKFRAME_REACH, XIAOHEI_BREAKFRAME_THINKING, XIAOHEI_BREAKFRAME_WORKING, } from './generated-keyart.js';
|
|
2
|
-
import { XIAOHEI_HOST_SELECTORS } from './host-contract.js';
|
|
3
|
-
import { subscribeXiaoheiHostDom } from './host-dom.js';
|
|
4
|
-
export const XIAOHEI_COMPOSER_AVATAR_CLASS = 'xiaohei-composer-avatar';
|
|
5
|
-
export const XIAOHEI_COMPOSER_IDLE_MOTIONS = [
|
|
6
|
-
'glance-left',
|
|
7
|
-
'glance-right',
|
|
8
|
-
'nod',
|
|
9
|
-
'perk',
|
|
10
|
-
'peek',
|
|
11
|
-
'double-blink',
|
|
12
|
-
'ponder',
|
|
13
|
-
];
|
|
14
|
-
/** Pick a varied idle gesture without visibly repeating the previous one. */
|
|
15
|
-
export function resolveXiaoheiComposerIdleMotion(random = Math.random, previous) {
|
|
16
|
-
const candidates = previous === undefined
|
|
17
|
-
? XIAOHEI_COMPOSER_IDLE_MOTIONS
|
|
18
|
-
: XIAOHEI_COMPOSER_IDLE_MOTIONS.filter(motion => motion !== previous);
|
|
19
|
-
const index = Math.min(candidates.length - 1, Math.max(0, Math.floor(random() * candidates.length)));
|
|
20
|
-
return candidates[index] ?? XIAOHEI_COMPOSER_IDLE_MOTIONS[0];
|
|
21
|
-
}
|
|
22
|
-
const XIAOHEI_IDLE_MOTION_DURATION = {
|
|
23
|
-
'glance-left': 1_760,
|
|
24
|
-
'glance-right': 1_760,
|
|
25
|
-
'nod': 1_520,
|
|
26
|
-
'perk': 1_640,
|
|
27
|
-
'peek': 1_860,
|
|
28
|
-
'double-blink': 760,
|
|
29
|
-
'ponder': 2_260,
|
|
30
|
-
};
|
|
31
|
-
/** Resolve the avatar target without coupling to generated Host class names. */
|
|
32
|
-
export function resolveXiaoheiComposerAvatarPosition(composer, viewportWidth, viewportHeight) {
|
|
33
|
-
const avatarWidth = 172;
|
|
34
|
-
const avatarHeight = 184;
|
|
35
|
-
const mobile = viewportWidth <= 760;
|
|
36
|
-
const hero = composer.top < viewportHeight * 0.58;
|
|
37
|
-
let placement;
|
|
38
|
-
let scale;
|
|
39
|
-
let x;
|
|
40
|
-
let y;
|
|
41
|
-
if (mobile) {
|
|
42
|
-
placement = 'mobile';
|
|
43
|
-
scale = 0.72;
|
|
44
|
-
x = composer.left + 8;
|
|
45
|
-
y = composer.top - avatarHeight * scale - 8;
|
|
46
|
-
}
|
|
47
|
-
else if (hero) {
|
|
48
|
-
placement = 'hero';
|
|
49
|
-
scale = 0.92;
|
|
50
|
-
x = composer.left + composer.width / 2 - avatarWidth / 2;
|
|
51
|
-
y = composer.top - avatarHeight * scale - 12;
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
placement = 'docked';
|
|
55
|
-
scale = 0.9;
|
|
56
|
-
x = composer.left - avatarWidth * scale - 16;
|
|
57
|
-
y = composer.bottom - avatarHeight * scale + 8;
|
|
58
|
-
}
|
|
59
|
-
return {
|
|
60
|
-
placement,
|
|
61
|
-
scale,
|
|
62
|
-
x: Math.round(Math.max(8, Math.min(viewportWidth - avatarWidth * scale - 8, x))),
|
|
63
|
-
y: Math.round(Math.max(8, Math.min(viewportHeight - avatarHeight * scale - 8, y))),
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
/** Mount one persistent avatar and let the native composer remain fully owned by DSH. */
|
|
67
|
-
export function installXiaoheiComposerAvatar(doc = typeof document === 'undefined' ? undefined : document) {
|
|
68
|
-
if (doc === undefined)
|
|
69
|
-
return () => { };
|
|
70
|
-
const win = doc.defaultView;
|
|
71
|
-
if (win === null)
|
|
72
|
-
return () => { };
|
|
73
|
-
doc.querySelector(`.${XIAOHEI_COMPOSER_AVATAR_CLASS}`)?.remove();
|
|
74
|
-
const avatar = doc.createElement('span');
|
|
75
|
-
avatar.className = XIAOHEI_COMPOSER_AVATAR_CLASS;
|
|
76
|
-
avatar.setAttribute('aria-hidden', 'true');
|
|
77
|
-
avatar.dataset.xiaoheiPortrait = 'idle';
|
|
78
|
-
const effectsBack = createAvatarLayer(doc, 'effects-back');
|
|
79
|
-
const ringBack = createAvatarLayer(doc, 'ring-back');
|
|
80
|
-
const circle = createAvatarLayer(doc, 'circle');
|
|
81
|
-
circle.append(...createPortraitImages(doc, 'inside'));
|
|
82
|
-
const overflow = createAvatarLayer(doc, 'overflow');
|
|
83
|
-
overflow.append(...createPortraitImages(doc, 'overflow'));
|
|
84
|
-
const ringFront = createAvatarLayer(doc, 'ring-front');
|
|
85
|
-
const breakoutRight = createAvatarLayer(doc, 'breakout-right');
|
|
86
|
-
breakoutRight.append(...createBreakoutRightImages(doc));
|
|
87
|
-
const effectsFront = createAvatarLayer(doc, 'effects-front');
|
|
88
|
-
avatar.append(effectsBack, ringBack, circle, overflow, ringFront, breakoutRight, effectsFront);
|
|
89
|
-
doc.body.append(avatar);
|
|
90
|
-
let disposed = false;
|
|
91
|
-
let composer;
|
|
92
|
-
let resizeObserver;
|
|
93
|
-
let frameRequest;
|
|
94
|
-
let pointerRequest;
|
|
95
|
-
let reactionTimer;
|
|
96
|
-
let reactionStageTimers = [];
|
|
97
|
-
let stateTimer;
|
|
98
|
-
let blinkTimer;
|
|
99
|
-
let blinkResetTimer;
|
|
100
|
-
let idleTimer;
|
|
101
|
-
let idleResetTimer;
|
|
102
|
-
let portraitRequest = 0;
|
|
103
|
-
let reactionRequest = 0;
|
|
104
|
-
let previousIdleMotion;
|
|
105
|
-
let desiredHostPortrait = resolveDisplayPortrait(doc.documentElement.dataset.xiaoheiState);
|
|
106
|
-
let layoutReady = false;
|
|
107
|
-
let idlePortraitReady = false;
|
|
108
|
-
let pointerX = 0;
|
|
109
|
-
let pointerY = 0;
|
|
110
|
-
const revealAvatar = () => {
|
|
111
|
-
if (layoutReady && idlePortraitReady)
|
|
112
|
-
avatar.dataset.xiaoheiAvatarReady = 'true';
|
|
113
|
-
};
|
|
114
|
-
const portraitImages = Array.from(avatar.querySelectorAll('[data-xiaohei-portrait-frame]'));
|
|
115
|
-
const imagesByState = new Map();
|
|
116
|
-
for (const image of portraitImages) {
|
|
117
|
-
const state = image.dataset.xiaoheiPortraitFrame;
|
|
118
|
-
const images = imagesByState.get(state) ?? [];
|
|
119
|
-
images.push(image);
|
|
120
|
-
imagesByState.set(state, images);
|
|
121
|
-
}
|
|
122
|
-
const decodedStates = new Set();
|
|
123
|
-
const decodeTasks = new Map();
|
|
124
|
-
const ensurePortraitDecoded = (state) => {
|
|
125
|
-
if (decodedStates.has(state))
|
|
126
|
-
return Promise.resolve(true);
|
|
127
|
-
const existing = decodeTasks.get(state);
|
|
128
|
-
if (existing !== undefined)
|
|
129
|
-
return existing;
|
|
130
|
-
const task = Promise.all((imagesByState.get(state) ?? []).map(decodePortraitImage))
|
|
131
|
-
.then((results) => {
|
|
132
|
-
const decoded = results.length > 0 && results.every(Boolean);
|
|
133
|
-
if (decoded)
|
|
134
|
-
decodedStates.add(state);
|
|
135
|
-
return decoded;
|
|
136
|
-
});
|
|
137
|
-
decodeTasks.set(state, task);
|
|
138
|
-
return task;
|
|
139
|
-
};
|
|
140
|
-
const showPortrait = async (state) => {
|
|
141
|
-
const request = ++portraitRequest;
|
|
142
|
-
const decoded = await ensurePortraitDecoded(state);
|
|
143
|
-
if (disposed || request !== portraitRequest || !decoded)
|
|
144
|
-
return;
|
|
145
|
-
avatar.dataset.xiaoheiPortrait = state;
|
|
146
|
-
};
|
|
147
|
-
const applyHostPortrait = () => {
|
|
148
|
-
if (avatar.dataset.xiaoheiAvatarReaction !== undefined)
|
|
149
|
-
return;
|
|
150
|
-
void showPortrait(desiredHostPortrait);
|
|
151
|
-
};
|
|
152
|
-
const scheduleHostPortrait = () => {
|
|
153
|
-
desiredHostPortrait = resolveDisplayPortrait(doc.documentElement.dataset.xiaoheiState);
|
|
154
|
-
if (stateTimer !== undefined)
|
|
155
|
-
clearTimeout(stateTimer);
|
|
156
|
-
stateTimer = setTimeout(() => {
|
|
157
|
-
stateTimer = undefined;
|
|
158
|
-
applyHostPortrait();
|
|
159
|
-
}, 150);
|
|
160
|
-
};
|
|
161
|
-
const measure = () => {
|
|
162
|
-
frameRequest = undefined;
|
|
163
|
-
if (disposed || composer === undefined || !composer.isConnected) {
|
|
164
|
-
avatar.removeAttribute('data-xiaohei-avatar-ready');
|
|
165
|
-
layoutReady = false;
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
const bounds = composer.getBoundingClientRect();
|
|
169
|
-
const viewport = win.visualViewport;
|
|
170
|
-
const viewportWidth = viewport?.width ?? win.innerWidth;
|
|
171
|
-
const viewportHeight = viewport?.height ?? win.innerHeight;
|
|
172
|
-
const position = resolveXiaoheiComposerAvatarPosition(bounds, viewportWidth, viewportHeight);
|
|
173
|
-
avatar.style.setProperty('--xiaohei-composer-avatar-x', `${position.x}px`);
|
|
174
|
-
avatar.style.setProperty('--xiaohei-composer-avatar-y', `${position.y}px`);
|
|
175
|
-
avatar.style.setProperty('--xiaohei-composer-avatar-scale', String(position.scale));
|
|
176
|
-
avatar.dataset.xiaoheiAvatarPlacement = position.placement;
|
|
177
|
-
if (!layoutReady) {
|
|
178
|
-
avatar.getBoundingClientRect();
|
|
179
|
-
layoutReady = true;
|
|
180
|
-
revealAvatar();
|
|
181
|
-
}
|
|
182
|
-
};
|
|
183
|
-
const scheduleMeasure = () => {
|
|
184
|
-
if (disposed || frameRequest !== undefined)
|
|
185
|
-
return;
|
|
186
|
-
frameRequest = win.requestAnimationFrame(measure);
|
|
187
|
-
};
|
|
188
|
-
const bindComposer = () => {
|
|
189
|
-
const next = doc.querySelector(XIAOHEI_HOST_SELECTORS.composerCard) ?? undefined;
|
|
190
|
-
if (next !== composer) {
|
|
191
|
-
resizeObserver?.disconnect();
|
|
192
|
-
resizeObserver = undefined;
|
|
193
|
-
composer = next;
|
|
194
|
-
if (composer !== undefined && typeof win.ResizeObserver === 'function') {
|
|
195
|
-
resizeObserver = new win.ResizeObserver(scheduleMeasure);
|
|
196
|
-
resizeObserver.observe(composer);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
scheduleMeasure();
|
|
200
|
-
};
|
|
201
|
-
const handleViewportChange = () => scheduleMeasure();
|
|
202
|
-
const renderPointerResponse = () => {
|
|
203
|
-
pointerRequest = undefined;
|
|
204
|
-
const bounds = avatar.getBoundingClientRect();
|
|
205
|
-
const centerX = bounds.left + bounds.width / 2;
|
|
206
|
-
const centerY = bounds.top + bounds.height / 2;
|
|
207
|
-
const deltaX = pointerX - centerX;
|
|
208
|
-
const deltaY = pointerY - centerY;
|
|
209
|
-
const distance = Math.hypot(deltaX, deltaY);
|
|
210
|
-
const proximity = Math.max(0, 1 - distance / 220);
|
|
211
|
-
avatar.style.setProperty('--xiaohei-avatar-look-x', `${Math.max(-2.5, Math.min(2.5, deltaX / 62)) * proximity}px`);
|
|
212
|
-
avatar.style.setProperty('--xiaohei-avatar-look-y', `${Math.max(-1.6, Math.min(1.6, deltaY / 88)) * proximity}px`);
|
|
213
|
-
avatar.style.setProperty('--xiaohei-avatar-look-rotation', `${Math.max(-1.2, Math.min(1.2, deltaX / 170)) * proximity}deg`);
|
|
214
|
-
avatar.toggleAttribute('data-xiaohei-avatar-aware', proximity > 0);
|
|
215
|
-
avatar.toggleAttribute('data-xiaohei-avatar-near', distance < 104);
|
|
216
|
-
};
|
|
217
|
-
const handlePointerMove = (event) => {
|
|
218
|
-
pointerX = event.clientX;
|
|
219
|
-
pointerY = event.clientY;
|
|
220
|
-
if (pointerRequest === undefined)
|
|
221
|
-
pointerRequest = win.requestAnimationFrame(renderPointerResponse);
|
|
222
|
-
};
|
|
223
|
-
const handleAvatarClick = () => {
|
|
224
|
-
if (avatar.dataset.xiaoheiAvatarReaction !== undefined)
|
|
225
|
-
return;
|
|
226
|
-
if (reactionTimer !== undefined)
|
|
227
|
-
clearTimeout(reactionTimer);
|
|
228
|
-
for (const timer of reactionStageTimers)
|
|
229
|
-
clearTimeout(timer);
|
|
230
|
-
reactionStageTimers = [];
|
|
231
|
-
const request = ++reactionRequest;
|
|
232
|
-
if (idleResetTimer !== undefined)
|
|
233
|
-
clearTimeout(idleResetTimer);
|
|
234
|
-
idleResetTimer = undefined;
|
|
235
|
-
delete avatar.dataset.xiaoheiAvatarIdle;
|
|
236
|
-
avatar.dataset.xiaoheiAvatarReaction = 'touch';
|
|
237
|
-
avatar.dataset.xiaoheiAvatarReactionStage = 'anticipate';
|
|
238
|
-
reactionStageTimers.push(setTimeout(() => {
|
|
239
|
-
if (request !== reactionRequest)
|
|
240
|
-
return;
|
|
241
|
-
avatar.dataset.xiaoheiAvatarReactionStage = 'brace';
|
|
242
|
-
void showPortrait('brace');
|
|
243
|
-
}, 170), setTimeout(() => {
|
|
244
|
-
if (request !== reactionRequest)
|
|
245
|
-
return;
|
|
246
|
-
avatar.dataset.xiaoheiAvatarReactionStage = 'break';
|
|
247
|
-
void showPortrait('reach');
|
|
248
|
-
}, 430), setTimeout(() => {
|
|
249
|
-
if (request !== reactionRequest)
|
|
250
|
-
return;
|
|
251
|
-
avatar.dataset.xiaoheiAvatarReactionStage = 'recover';
|
|
252
|
-
void showPortrait('brace');
|
|
253
|
-
}, 820), setTimeout(() => {
|
|
254
|
-
if (request !== reactionRequest)
|
|
255
|
-
return;
|
|
256
|
-
avatar.dataset.xiaoheiAvatarReactionStage = 'settle';
|
|
257
|
-
void showPortrait(desiredHostPortrait);
|
|
258
|
-
}, 1_090));
|
|
259
|
-
reactionTimer = setTimeout(() => {
|
|
260
|
-
if (request !== reactionRequest)
|
|
261
|
-
return;
|
|
262
|
-
delete avatar.dataset.xiaoheiAvatarReaction;
|
|
263
|
-
delete avatar.dataset.xiaoheiAvatarReactionStage;
|
|
264
|
-
reactionTimer = undefined;
|
|
265
|
-
reactionStageTimers = [];
|
|
266
|
-
applyHostPortrait();
|
|
267
|
-
}, 1_340);
|
|
268
|
-
};
|
|
269
|
-
const scheduleBlink = () => {
|
|
270
|
-
if (disposed || blinkTimer !== undefined)
|
|
271
|
-
return;
|
|
272
|
-
blinkTimer = setTimeout(() => {
|
|
273
|
-
blinkTimer = undefined;
|
|
274
|
-
if (!doc.hidden
|
|
275
|
-
&& avatar.dataset.xiaoheiPortrait === 'idle'
|
|
276
|
-
&& avatar.dataset.xiaoheiAvatarReaction === undefined
|
|
277
|
-
&& avatar.dataset.xiaoheiAvatarIdle === undefined) {
|
|
278
|
-
void ensurePortraitDecoded('blink').then((decoded) => {
|
|
279
|
-
if (!decoded || disposed || avatar.dataset.xiaoheiPortrait !== 'idle')
|
|
280
|
-
return;
|
|
281
|
-
avatar.dataset.xiaoheiAvatarBlink = 'true';
|
|
282
|
-
if (blinkResetTimer !== undefined)
|
|
283
|
-
clearTimeout(blinkResetTimer);
|
|
284
|
-
blinkResetTimer = setTimeout(() => {
|
|
285
|
-
delete avatar.dataset.xiaoheiAvatarBlink;
|
|
286
|
-
blinkResetTimer = undefined;
|
|
287
|
-
}, 130);
|
|
288
|
-
});
|
|
289
|
-
}
|
|
290
|
-
scheduleBlink();
|
|
291
|
-
}, 4200 + Math.random() * 3600);
|
|
292
|
-
};
|
|
293
|
-
const scheduleIdleMotion = () => {
|
|
294
|
-
if (disposed || idleTimer !== undefined)
|
|
295
|
-
return;
|
|
296
|
-
idleTimer = setTimeout(() => {
|
|
297
|
-
idleTimer = undefined;
|
|
298
|
-
if (!doc.hidden
|
|
299
|
-
&& desiredHostPortrait === 'idle'
|
|
300
|
-
&& avatar.dataset.xiaoheiAvatarReaction === undefined) {
|
|
301
|
-
const motion = resolveXiaoheiComposerIdleMotion(Math.random, previousIdleMotion);
|
|
302
|
-
previousIdleMotion = motion;
|
|
303
|
-
avatar.dataset.xiaoheiAvatarIdle = motion;
|
|
304
|
-
if (motion === 'ponder')
|
|
305
|
-
void showPortrait('thinking');
|
|
306
|
-
idleResetTimer = setTimeout(() => {
|
|
307
|
-
delete avatar.dataset.xiaoheiAvatarIdle;
|
|
308
|
-
idleResetTimer = undefined;
|
|
309
|
-
if (motion === 'ponder')
|
|
310
|
-
applyHostPortrait();
|
|
311
|
-
}, XIAOHEI_IDLE_MOTION_DURATION[motion]);
|
|
312
|
-
}
|
|
313
|
-
scheduleIdleMotion();
|
|
314
|
-
}, 4_800 + Math.random() * 5_600);
|
|
315
|
-
};
|
|
316
|
-
const handleTransitionEnd = (event) => {
|
|
317
|
-
if (composer === undefined)
|
|
318
|
-
return;
|
|
319
|
-
const target = event.target;
|
|
320
|
-
if (target instanceof win.Node && (target === composer || composer.contains(target)))
|
|
321
|
-
scheduleMeasure();
|
|
322
|
-
};
|
|
323
|
-
const unsubscribeHostDom = subscribeXiaoheiHostDom(doc, bindComposer);
|
|
324
|
-
const stateObserver = new win.MutationObserver(scheduleHostPortrait);
|
|
325
|
-
stateObserver.observe(doc.documentElement, {
|
|
326
|
-
attributes: true,
|
|
327
|
-
attributeFilter: ['data-xiaohei-state'],
|
|
328
|
-
});
|
|
329
|
-
win.addEventListener('resize', handleViewportChange, { passive: true });
|
|
330
|
-
win.addEventListener('pointermove', handlePointerMove, { passive: true });
|
|
331
|
-
win.visualViewport?.addEventListener('resize', handleViewportChange, { passive: true });
|
|
332
|
-
win.visualViewport?.addEventListener('scroll', handleViewportChange, { passive: true });
|
|
333
|
-
doc.addEventListener('transitionend', handleTransitionEnd, true);
|
|
334
|
-
avatar.addEventListener('click', handleAvatarClick);
|
|
335
|
-
bindComposer();
|
|
336
|
-
void ensurePortraitDecoded('idle').then((decoded) => {
|
|
337
|
-
if (!decoded || disposed)
|
|
338
|
-
return;
|
|
339
|
-
idlePortraitReady = true;
|
|
340
|
-
revealAvatar();
|
|
341
|
-
});
|
|
342
|
-
for (const [state] of PORTRAIT_SOURCES) {
|
|
343
|
-
if (state !== 'idle')
|
|
344
|
-
void ensurePortraitDecoded(state);
|
|
345
|
-
}
|
|
346
|
-
scheduleHostPortrait();
|
|
347
|
-
scheduleBlink();
|
|
348
|
-
scheduleIdleMotion();
|
|
349
|
-
return () => {
|
|
350
|
-
disposed = true;
|
|
351
|
-
unsubscribeHostDom();
|
|
352
|
-
stateObserver.disconnect();
|
|
353
|
-
resizeObserver?.disconnect();
|
|
354
|
-
if (frameRequest !== undefined)
|
|
355
|
-
win.cancelAnimationFrame(frameRequest);
|
|
356
|
-
if (pointerRequest !== undefined)
|
|
357
|
-
win.cancelAnimationFrame(pointerRequest);
|
|
358
|
-
if (reactionTimer !== undefined)
|
|
359
|
-
clearTimeout(reactionTimer);
|
|
360
|
-
for (const timer of reactionStageTimers)
|
|
361
|
-
clearTimeout(timer);
|
|
362
|
-
if (stateTimer !== undefined)
|
|
363
|
-
clearTimeout(stateTimer);
|
|
364
|
-
if (blinkTimer !== undefined)
|
|
365
|
-
clearTimeout(blinkTimer);
|
|
366
|
-
if (blinkResetTimer !== undefined)
|
|
367
|
-
clearTimeout(blinkResetTimer);
|
|
368
|
-
if (idleTimer !== undefined)
|
|
369
|
-
clearTimeout(idleTimer);
|
|
370
|
-
if (idleResetTimer !== undefined)
|
|
371
|
-
clearTimeout(idleResetTimer);
|
|
372
|
-
win.removeEventListener('resize', handleViewportChange);
|
|
373
|
-
win.removeEventListener('pointermove', handlePointerMove);
|
|
374
|
-
win.visualViewport?.removeEventListener('resize', handleViewportChange);
|
|
375
|
-
win.visualViewport?.removeEventListener('scroll', handleViewportChange);
|
|
376
|
-
doc.removeEventListener('transitionend', handleTransitionEnd, true);
|
|
377
|
-
avatar.removeEventListener('click', handleAvatarClick);
|
|
378
|
-
avatar.remove();
|
|
379
|
-
};
|
|
380
|
-
}
|
|
381
|
-
function createAvatarImage(doc, source, state) {
|
|
382
|
-
const image = doc.createElement('img');
|
|
383
|
-
image.className = `${XIAOHEI_COMPOSER_AVATAR_CLASS}__image ${XIAOHEI_COMPOSER_AVATAR_CLASS}__image--${state}`;
|
|
384
|
-
image.alt = '';
|
|
385
|
-
image.decoding = 'async';
|
|
386
|
-
const portraitState = state.slice(state.lastIndexOf('-') + 1);
|
|
387
|
-
image.dataset.xiaoheiPortraitFrame = portraitState;
|
|
388
|
-
image.fetchPriority = portraitState === 'idle' ? 'high' : 'low';
|
|
389
|
-
image.src = source;
|
|
390
|
-
return image;
|
|
391
|
-
}
|
|
392
|
-
function resolveDisplayPortrait(state) {
|
|
393
|
-
switch (state) {
|
|
394
|
-
case 'thinking':
|
|
395
|
-
case 'waiting':
|
|
396
|
-
return 'thinking';
|
|
397
|
-
case 'tool':
|
|
398
|
-
case 'streaming':
|
|
399
|
-
return 'working';
|
|
400
|
-
case 'complete':
|
|
401
|
-
return 'complete';
|
|
402
|
-
case 'error':
|
|
403
|
-
return 'error';
|
|
404
|
-
default:
|
|
405
|
-
return 'idle';
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
async function decodePortraitImage(image) {
|
|
409
|
-
try {
|
|
410
|
-
if (typeof image.decode === 'function')
|
|
411
|
-
await image.decode();
|
|
412
|
-
return image.naturalWidth > 0 || image.complete;
|
|
413
|
-
}
|
|
414
|
-
catch {
|
|
415
|
-
return image.complete && image.naturalWidth > 0;
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
const PORTRAIT_SOURCES = [
|
|
419
|
-
['idle', XIAOHEI_BREAKFRAME_IDLE],
|
|
420
|
-
['blink', XIAOHEI_BREAKFRAME_BLINK],
|
|
421
|
-
['brace', XIAOHEI_BREAKFRAME_BRACE],
|
|
422
|
-
['reach', XIAOHEI_BREAKFRAME_REACH],
|
|
423
|
-
['thinking', XIAOHEI_BREAKFRAME_THINKING],
|
|
424
|
-
['working', XIAOHEI_BREAKFRAME_WORKING],
|
|
425
|
-
['complete', XIAOHEI_BREAKFRAME_COMPLETE],
|
|
426
|
-
['error', XIAOHEI_BREAKFRAME_ERROR],
|
|
427
|
-
];
|
|
428
|
-
function createPortraitImages(doc, layer) {
|
|
429
|
-
return PORTRAIT_SOURCES.map(([state, source]) => createAvatarImage(doc, source, `${layer}-${state}`));
|
|
430
|
-
}
|
|
431
|
-
function createBreakoutRightImages(doc) {
|
|
432
|
-
return PORTRAIT_SOURCES
|
|
433
|
-
.filter(([state]) => state === 'brace' || state === 'reach')
|
|
434
|
-
.map(([state, source]) => createAvatarImage(doc, source, `breakout-right-${state}`));
|
|
435
|
-
}
|
|
436
|
-
function createAvatarLayer(doc, name) {
|
|
437
|
-
const layer = doc.createElement('span');
|
|
438
|
-
layer.className = `${XIAOHEI_COMPOSER_AVATAR_CLASS}__${name}`;
|
|
439
|
-
return layer;
|
|
440
|
-
}
|
|
441
|
-
//# sourceMappingURL=composer-avatar.js.map
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
2
|
-
/** A read-only local projection. The native editor owns draft and send lifetime. */
|
|
3
|
-
export declare function XiaoheiDraftPreview({ input }: PropsRuntime<'conversation.input.dock'>): import("react").JSX.Element | null;
|
|
4
|
-
//# sourceMappingURL=composer-draft-preview.d.ts.map
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
/** A read-only local projection. The native editor owns draft and send lifetime. */
|
|
3
|
-
export function XiaoheiDraftPreview({ input }) {
|
|
4
|
-
if (!input.draft.trim() || input.phase === 'submitting' || input.phase === 'adjudicating')
|
|
5
|
-
return null;
|
|
6
|
-
return _jsxs("section", { "data-xiaohei-draft-preview": true, "aria-label": "\u8349\u7A3F \u00B7 \u672A\u53D1\u9001", children: [_jsx("div", { className: "xiaohei-draft-label", children: "\u8349\u7A3F \u00B7 \u672A\u53D1\u9001" }), _jsx("div", { className: "xiaohei-draft-bubble", tabIndex: 0, "aria-label": "\u8349\u7A3F\u5185\u5BB9", children: input.draft })] });
|
|
7
|
-
}
|
|
8
|
-
//# sourceMappingURL=composer-draft-preview.js.map
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/** Keep idle blinks sparse without making their rhythm mechanical. */
|
|
2
|
-
export declare function resolveXiaoheiSendBlinkDelay(random?: () => number): number;
|
|
3
|
-
/**
|
|
4
|
-
* Turn the Host's real primary button into Heixiu without replacing its click,
|
|
5
|
-
* keyboard, disabled, tooltip, or accessible-name behaviour.
|
|
6
|
-
*/
|
|
7
|
-
export declare function installXiaoheiComposerSendHeixiu(doc?: Document | undefined): () => void;
|
|
8
|
-
//# sourceMappingURL=composer-send-heixiu.d.ts.map
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import { XIAOHEI_HEIXIU_BLINK, XIAOHEI_HEIXIU_OPEN } from './generated-keyart.js';
|
|
2
|
-
import { XIAOHEI_HOST_SELECTORS } from './host-contract.js';
|
|
3
|
-
import { subscribeXiaoheiHostDom } from './host-dom.js';
|
|
4
|
-
const SEND_BUTTON_SELECTOR = ':scope > :last-child > :last-child > button:last-child';
|
|
5
|
-
const SEND_ATTRIBUTE = 'data-xiaohei-send-heixiu';
|
|
6
|
-
const BLINK_ATTRIBUTE = 'data-xiaohei-blink';
|
|
7
|
-
const HEIXIU_CLASS = 'xiaohei-composer-send-heixiu';
|
|
8
|
-
const BLINK_DELAY_MIN_MS = 4600;
|
|
9
|
-
const BLINK_DELAY_MAX_MS = 8200;
|
|
10
|
-
const BLINK_CLOSED_MS = 128;
|
|
11
|
-
/** Keep idle blinks sparse without making their rhythm mechanical. */
|
|
12
|
-
export function resolveXiaoheiSendBlinkDelay(random = Math.random) {
|
|
13
|
-
const sample = Math.min(1, Math.max(0, random()));
|
|
14
|
-
return Math.round(BLINK_DELAY_MIN_MS + sample * (BLINK_DELAY_MAX_MS - BLINK_DELAY_MIN_MS));
|
|
15
|
-
}
|
|
16
|
-
function createFrame(doc, source, className) {
|
|
17
|
-
const image = doc.createElement('img');
|
|
18
|
-
image.className = className;
|
|
19
|
-
image.src = source;
|
|
20
|
-
image.alt = '';
|
|
21
|
-
image.draggable = false;
|
|
22
|
-
return image;
|
|
23
|
-
}
|
|
24
|
-
function createHeixiu(doc) {
|
|
25
|
-
const element = doc.createElement('span');
|
|
26
|
-
element.className = HEIXIU_CLASS;
|
|
27
|
-
element.setAttribute('aria-hidden', 'true');
|
|
28
|
-
element.append(createFrame(doc, XIAOHEI_HEIXIU_OPEN, `${HEIXIU_CLASS}__open`), createFrame(doc, XIAOHEI_HEIXIU_BLINK, `${HEIXIU_CLASS}__blink`));
|
|
29
|
-
return element;
|
|
30
|
-
}
|
|
31
|
-
/** The Host renders a rect only when the primary action has become Stop. */
|
|
32
|
-
function isSendAction(button) {
|
|
33
|
-
const hostGlyph = [...button.children].find(child => child.localName === 'svg');
|
|
34
|
-
return hostGlyph !== undefined && hostGlyph.querySelector('rect') === null;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Turn the Host's real primary button into Heixiu without replacing its click,
|
|
38
|
-
* keyboard, disabled, tooltip, or accessible-name behaviour.
|
|
39
|
-
*/
|
|
40
|
-
export function installXiaoheiComposerSendHeixiu(doc = typeof document === 'undefined' ? undefined : document) {
|
|
41
|
-
if (doc?.body === undefined || doc.defaultView === null)
|
|
42
|
-
return () => { };
|
|
43
|
-
const win = doc.defaultView;
|
|
44
|
-
const reducedMotion = win.matchMedia('(prefers-reduced-motion: reduce)');
|
|
45
|
-
const decorations = new Map();
|
|
46
|
-
let blinkTimer = 0;
|
|
47
|
-
let reopenTimer = 0;
|
|
48
|
-
const canBlink = () => (decorations.size > 0
|
|
49
|
-
&& doc.visibilityState !== 'hidden'
|
|
50
|
-
&& !reducedMotion.matches);
|
|
51
|
-
const setClosed = (closed) => {
|
|
52
|
-
for (const decoration of decorations.values()) {
|
|
53
|
-
if (closed)
|
|
54
|
-
decoration.setAttribute(BLINK_ATTRIBUTE, 'closed');
|
|
55
|
-
else
|
|
56
|
-
decoration.removeAttribute(BLINK_ATTRIBUTE);
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
const clearTimers = () => {
|
|
60
|
-
if (blinkTimer !== 0)
|
|
61
|
-
win.clearTimeout(blinkTimer);
|
|
62
|
-
if (reopenTimer !== 0)
|
|
63
|
-
win.clearTimeout(reopenTimer);
|
|
64
|
-
blinkTimer = 0;
|
|
65
|
-
reopenTimer = 0;
|
|
66
|
-
};
|
|
67
|
-
const scheduleBlink = () => {
|
|
68
|
-
if (!canBlink() || blinkTimer !== 0 || reopenTimer !== 0)
|
|
69
|
-
return;
|
|
70
|
-
blinkTimer = win.setTimeout(() => {
|
|
71
|
-
blinkTimer = 0;
|
|
72
|
-
if (!canBlink())
|
|
73
|
-
return;
|
|
74
|
-
setClosed(true);
|
|
75
|
-
reopenTimer = win.setTimeout(() => {
|
|
76
|
-
reopenTimer = 0;
|
|
77
|
-
setClosed(false);
|
|
78
|
-
scheduleBlink();
|
|
79
|
-
}, BLINK_CLOSED_MS);
|
|
80
|
-
}, resolveXiaoheiSendBlinkDelay());
|
|
81
|
-
};
|
|
82
|
-
const restartBlink = () => {
|
|
83
|
-
clearTimers();
|
|
84
|
-
setClosed(false);
|
|
85
|
-
scheduleBlink();
|
|
86
|
-
};
|
|
87
|
-
const detach = (button, decoration) => {
|
|
88
|
-
decoration.remove();
|
|
89
|
-
button.removeAttribute(SEND_ATTRIBUTE);
|
|
90
|
-
decorations.delete(button);
|
|
91
|
-
};
|
|
92
|
-
const reconcile = () => {
|
|
93
|
-
const candidates = new Set();
|
|
94
|
-
for (const card of doc.querySelectorAll(XIAOHEI_HOST_SELECTORS.composerCard)) {
|
|
95
|
-
const button = card.querySelector(SEND_BUTTON_SELECTOR);
|
|
96
|
-
if (button !== null && isSendAction(button))
|
|
97
|
-
candidates.add(button);
|
|
98
|
-
}
|
|
99
|
-
const hadDecorations = decorations.size > 0;
|
|
100
|
-
for (const [button, decoration] of decorations) {
|
|
101
|
-
if (candidates.has(button) && decoration.parentElement === button)
|
|
102
|
-
continue;
|
|
103
|
-
detach(button, decoration);
|
|
104
|
-
}
|
|
105
|
-
for (const button of candidates) {
|
|
106
|
-
if (decorations.has(button))
|
|
107
|
-
continue;
|
|
108
|
-
const decoration = createHeixiu(doc);
|
|
109
|
-
button.setAttribute(SEND_ATTRIBUTE, 'true');
|
|
110
|
-
button.insertBefore(decoration, button.firstChild);
|
|
111
|
-
decorations.set(button, decoration);
|
|
112
|
-
}
|
|
113
|
-
if (!hadDecorations && decorations.size > 0)
|
|
114
|
-
scheduleBlink();
|
|
115
|
-
else if (hadDecorations && decorations.size === 0)
|
|
116
|
-
restartBlink();
|
|
117
|
-
};
|
|
118
|
-
const onEnvironmentChange = () => restartBlink();
|
|
119
|
-
reconcile();
|
|
120
|
-
const unsubscribeHostDom = subscribeXiaoheiHostDom(doc, reconcile);
|
|
121
|
-
doc.addEventListener('visibilitychange', onEnvironmentChange);
|
|
122
|
-
reducedMotion.addEventListener('change', onEnvironmentChange);
|
|
123
|
-
return () => {
|
|
124
|
-
clearTimers();
|
|
125
|
-
unsubscribeHostDom();
|
|
126
|
-
doc.removeEventListener('visibilitychange', onEnvironmentChange);
|
|
127
|
-
reducedMotion.removeEventListener('change', onEnvironmentChange);
|
|
128
|
-
for (const [button, decoration] of decorations)
|
|
129
|
-
detach(button, decoration);
|
|
130
|
-
decorations.clear();
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
//# sourceMappingURL=composer-send-heixiu.js.map
|
package/lib/current-session.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { SessionListState, SessionSummary } from '@deepseek-ai/dsh-api-session-controller/client';
|
|
2
|
-
/** Keep the host session-selection contract out of visual state reducers. */
|
|
3
|
-
export declare function currentSession(state: SessionListState & {
|
|
4
|
-
current?: SessionSummary['id'];
|
|
5
|
-
}): SessionSummary['id'] | undefined;
|
|
6
|
-
//# sourceMappingURL=current-session.d.ts.map
|
package/lib/current-session.js
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
/** Keep the host session-selection contract out of visual state reducers. */
|
|
2
|
-
export function currentSession(state) {
|
|
3
|
-
return Object.values(state.byId ?? {}).find(row => (row.retainedBy?.mainView ?? 0) > 0)?.id ?? state.current;
|
|
4
|
-
}
|
|
5
|
-
//# sourceMappingURL=current-session.js.map
|
package/lib/decorations-entry.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { installXiaoheiWallpaperCharacter } from './scene/wallpaper-character.js';
|
|
2
|
-
import { XIAOHEI_WALLPAPER_CHARACTER_CSS } from './scene/wallpaper-character-styles.js';
|
|
3
|
-
/** Self-contained native DSH chunk; no new HTTP routes or Desktop origin assumptions. */
|
|
4
|
-
export function installDecorations(doc) {
|
|
5
|
-
const style = doc.createElement('style');
|
|
6
|
-
style.id = 'dsh-theme-xiaohei/character-style';
|
|
7
|
-
style.textContent = XIAOHEI_WALLPAPER_CHARACTER_CSS;
|
|
8
|
-
doc.head.append(style);
|
|
9
|
-
try {
|
|
10
|
-
const disposeCharacter = installXiaoheiWallpaperCharacter(doc);
|
|
11
|
-
return () => { disposeCharacter(); style.remove(); };
|
|
12
|
-
}
|
|
13
|
-
catch (error) {
|
|
14
|
-
style.remove();
|
|
15
|
-
throw error;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
//# sourceMappingURL=decorations-entry.js.map
|