Skip to content

Commit 6206cf5

Browse files
committed
fix(desktop): hide fallback once sprite loads
1 parent 0c49eed commit 6206cf5

2 files changed

Lines changed: 55 additions & 14 deletions

File tree

apps/desktop/web/bridge.js

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,40 @@ function fallbackSpeech() {
7474
return document.getElementById('desktop-fallback-speech');
7575
}
7676

77+
function widgetShadow() {
78+
return root()?.firstElementChild?.shadowRoot ?? null;
79+
}
80+
81+
function widgetSprite() {
82+
return widgetShadow()?.querySelector('[class*="sprite"], [data-agent-pet-sprite], img') ?? null;
83+
}
84+
85+
function hasRealWidgetSprite() {
86+
const sprite = widgetSprite();
87+
if (!sprite) return false;
88+
const r = sprite.getBoundingClientRect();
89+
if (r.width <= 0 || r.height <= 0) return false;
90+
const style = getComputedStyle(sprite);
91+
return style.backgroundImage !== 'none' || sprite.tagName === 'IMG';
92+
}
93+
94+
function syncFallbackVisibility() {
95+
const el = fallbackPet();
96+
if (!el) return;
97+
el.hidden = hasRealWidgetSprite();
98+
}
99+
100+
function hideWidgetStartupBubble() {
101+
const shadow = widgetShadow();
102+
const candidates = shadow?.querySelectorAll('[class*="bubble"]') ?? [];
103+
for (const el of candidates) {
104+
const r = el.getBoundingClientRect();
105+
if (r.width > 0 && r.height > 0) {
106+
el.style.display = 'none';
107+
}
108+
}
109+
}
110+
77111
function resolveWidgetApi() {
78112
let api = null;
79113
try {
@@ -98,8 +132,8 @@ function resolveWidgetApi() {
98132

99133
function inspectWidget(label) {
100134
const host = root()?.firstElementChild;
101-
const shadow = host?.shadowRoot;
102-
const sprite = shadow?.querySelector('[class*="sprite"], [data-agent-pet-sprite], .ap-image, span');
135+
const shadow = widgetShadow();
136+
const sprite = widgetSprite() ?? shadow?.querySelector('.ap-image, span');
103137
const overlay = shadow?.querySelector('.ap-overlay');
104138
const spriteRect = sprite?.getBoundingClientRect();
105139
const overlayRect = overlay?.getBoundingClientRect();
@@ -139,7 +173,7 @@ function localRect(el) {
139173

140174
function findPetElement() {
141175
const host = root().firstElementChild;
142-
const widgetPet = host?.shadowRoot?.querySelector('[class*="sprite"], [data-agent-pet-sprite], img');
176+
const widgetPet = widgetSprite();
143177
if (widgetPet) {
144178
const r = widgetPet.getBoundingClientRect();
145179
if (r.width > 0 && r.height > 0) return widgetPet;
@@ -148,8 +182,7 @@ function findPetElement() {
148182
}
149183

150184
function findBubbleElement() {
151-
const host = root().firstElementChild;
152-
const candidates = host?.shadowRoot?.querySelectorAll('[class*="bubble"], a, output') ?? [];
185+
const candidates = widgetShadow()?.querySelectorAll('[class*="bubble"], a, output') ?? [];
153186
for (const el of candidates) {
154187
const r = el.getBoundingClientRect();
155188
if (r.width > 0 && r.height > 0) return el;
@@ -172,10 +205,16 @@ function observeBounds() {
172205
ro.observe(root());
173206
const pet = findPetElement();
174207
if (pet) ro.observe(pet);
175-
const mo = new MutationObserver(() => queueMicrotask(() => reportNow()));
208+
const mo = new MutationObserver(() => queueMicrotask(() => {
209+
syncFallbackVisibility();
210+
reportNow();
211+
}));
176212
mo.observe(root(), { subtree: true, childList: true, attributes: true, attributeFilter: ['style', 'class', 'hidden'] });
177213
window.addEventListener('resize', () => reportNow());
178-
setTimeout(() => reportNow(), 0);
214+
setTimeout(() => {
215+
syncFallbackVisibility();
216+
reportNow();
217+
}, 0);
179218
}
180219

181220
async function applyConfigAndReport() {
@@ -185,6 +224,8 @@ async function applyConfigAndReport() {
185224
registry = new Set(actionRegistry(launchConfig.manifest ?? launchConfig));
186225
await invoke('report_registry', { actions: [...registry] }).catch(() => {});
187226
diagnose('registry: reported', registry.size);
227+
hideWidgetStartupBubble();
228+
syncFallbackVisibility();
188229
reportNow();
189230
}
190231

@@ -215,13 +256,9 @@ observeBounds();
215256
wireDrag();
216257
applyConfigAndReport().catch((err) => console.warn('[agent-pet desktop] launch config failed', err));
217258
setTimeout(() => {
218-
try {
219-
widgetApi?.say('agent-pet is running', { ttl: 3500 });
220-
} catch (err) {
221-
diagnose('say: failed', err?.message ?? err);
222-
}
223-
setFallbackSpeech('agent-pet is running');
224-
inspectWidget('after say');
259+
hideWidgetStartupBubble();
260+
syncFallbackVisibility();
261+
inspectWidget('after settle');
225262
reportNow();
226263
}, 250);
227264

@@ -236,5 +273,6 @@ listen('pet:play', (event) => {
236273
listen('pet:say', (event) => {
237274
if (widgetApi) handleSayEvent(event.payload, widgetApi);
238275
setFallbackSpeech(event.payload?.text);
276+
syncFallbackVisibility();
239277
setTimeout(() => reportNow(), 0);
240278
});

apps/desktop/web/index.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
pointer-events: auto;
3535
z-index: 10;
3636
}
37+
#desktop-fallback-pet[hidden] {
38+
display: none;
39+
}
3740
#desktop-fallback-pet[data-state="building"],
3841
#desktop-fallback-pet[data-state="thinking"] {
3942
animation: fallback-bob 900ms ease-in-out infinite alternate;

0 commit comments

Comments
 (0)