@usero/sdk 1.1.12 → 1.1.13
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.
|
@@ -293,19 +293,77 @@ async function postNoteWithRetry(apiUrl, sessionId, atMs, text, logger) {
|
|
|
293
293
|
}
|
|
294
294
|
|
|
295
295
|
// src/plugins/user-test/ui.ts
|
|
296
|
+
var KEYBOARD_OPEN_MIN_INSET_PX = 80;
|
|
297
|
+
function computeKeyboardInset(innerHeight, viewportHeight, viewportOffsetTop) {
|
|
298
|
+
return Math.max(0, Math.round(innerHeight - (viewportHeight + viewportOffsetTop)));
|
|
299
|
+
}
|
|
300
|
+
function installKeyboardInsetWatcher(anchor) {
|
|
301
|
+
const viewport = window.visualViewport;
|
|
302
|
+
if (!viewport) return null;
|
|
303
|
+
let rafId = 0;
|
|
304
|
+
let lastInset = -1;
|
|
305
|
+
let resizeSeen = false;
|
|
306
|
+
const apply = () => {
|
|
307
|
+
rafId = 0;
|
|
308
|
+
const fromResize = resizeSeen;
|
|
309
|
+
resizeSeen = false;
|
|
310
|
+
const inset = computeKeyboardInset(window.innerHeight, viewport.height, viewport.offsetTop);
|
|
311
|
+
if (inset === lastInset) return;
|
|
312
|
+
lastInset = inset;
|
|
313
|
+
anchor.setAttribute("data-vv-scrolling", fromResize ? "false" : "true");
|
|
314
|
+
anchor.style.setProperty("--keyboard-inset", `${inset}px`);
|
|
315
|
+
anchor.style.setProperty("--vv-height", `${Math.round(viewport.height)}px`);
|
|
316
|
+
anchor.setAttribute("data-keyboard-open", inset >= KEYBOARD_OPEN_MIN_INSET_PX ? "true" : "false");
|
|
317
|
+
};
|
|
318
|
+
const schedule = () => {
|
|
319
|
+
if (rafId === 0) rafId = window.requestAnimationFrame(apply);
|
|
320
|
+
};
|
|
321
|
+
const onResize = () => {
|
|
322
|
+
resizeSeen = true;
|
|
323
|
+
schedule();
|
|
324
|
+
};
|
|
325
|
+
const onScroll = () => {
|
|
326
|
+
schedule();
|
|
327
|
+
};
|
|
328
|
+
viewport.addEventListener("resize", onResize);
|
|
329
|
+
viewport.addEventListener("scroll", onScroll);
|
|
330
|
+
resizeSeen = true;
|
|
331
|
+
apply();
|
|
332
|
+
return () => {
|
|
333
|
+
viewport.removeEventListener("resize", onResize);
|
|
334
|
+
viewport.removeEventListener("scroll", onScroll);
|
|
335
|
+
if (rafId !== 0) window.cancelAnimationFrame(rafId);
|
|
336
|
+
};
|
|
337
|
+
}
|
|
296
338
|
function buildIndicator(host, store, callbacks) {
|
|
297
339
|
const root = host.attachShadow({ mode: "open" });
|
|
298
340
|
const style = document.createElement("style");
|
|
299
341
|
style.textContent = `
|
|
300
342
|
:host { all: initial; }
|
|
301
343
|
.anchor {
|
|
344
|
+
/* --keyboard-inset is the height of the mobile soft keyboard, written by
|
|
345
|
+
the visualViewport watcher (0 when closed / unsupported). position:fixed
|
|
346
|
+
anchors to the LAYOUT viewport, which the keyboard does not shrink, so
|
|
347
|
+
without this the open keyboard covers the bar and task panel entirely. */
|
|
348
|
+
--keyboard-inset: 0px;
|
|
302
349
|
position: fixed;
|
|
303
|
-
bottom: calc(env(safe-area-inset-bottom, 0px) + 16px);
|
|
350
|
+
bottom: calc(env(safe-area-inset-bottom, 0px) + 16px + var(--keyboard-inset));
|
|
304
351
|
left: 50%; transform: translateX(-50%);
|
|
305
352
|
display: flex; flex-direction: column; align-items: center; gap: 8px;
|
|
306
353
|
z-index: 2147483646; max-width: calc(100vw - 32px);
|
|
307
354
|
font: 13px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
|
|
308
355
|
color: #fff;
|
|
356
|
+
/* Eased only for keyboard show/hide; scroll ticks suppress it below. */
|
|
357
|
+
transition: bottom 0.18s ease-out;
|
|
358
|
+
}
|
|
359
|
+
/* While the visual viewport is being panned (URL bar collapse, pinch,
|
|
360
|
+
keyboard-driven scroll) the inset must track 1:1, animating every tick
|
|
361
|
+
reads as lag. The watcher flips this attribute per update source. */
|
|
362
|
+
.anchor[data-vv-scrolling="true"] { transition: none; }
|
|
363
|
+
/* Keyboard open: the keyboard covers the home-indicator zone, so the
|
|
364
|
+
safe-area + 16px margin is dead space. Tuck in to an 8px gap instead. */
|
|
365
|
+
.anchor[data-keyboard-open="true"] {
|
|
366
|
+
bottom: calc(var(--keyboard-inset) + 8px);
|
|
309
367
|
}
|
|
310
368
|
.bar {
|
|
311
369
|
display: inline-flex; align-items: center; gap: 6px;
|
|
@@ -328,6 +386,16 @@ function buildIndicator(host, store, callbacks) {
|
|
|
328
386
|
width: max-content; overflow-y: auto;
|
|
329
387
|
}
|
|
330
388
|
.panel[hidden] { display: none; }
|
|
389
|
+
/* Compact state while the keyboard is up: 60vh is measured against the
|
|
390
|
+
LAYOUT viewport and can exceed the visible strip above the keyboard,
|
|
391
|
+
clipping the instructions. Cap against the VISUAL viewport height
|
|
392
|
+
(--vv-height, written by the watcher) minus the bar's footprint, with a
|
|
393
|
+
96px floor so at least a couple of lines stay readable and scrollable.
|
|
394
|
+
Slightly tighter padding to make the most of the scarce space. */
|
|
395
|
+
.anchor[data-keyboard-open="true"] .panel {
|
|
396
|
+
max-height: min(480px, max(96px, calc(var(--vv-height, 100vh) - 96px)));
|
|
397
|
+
padding: 10px 12px 10px 8px;
|
|
398
|
+
}
|
|
331
399
|
.panel ol { margin: 0; padding-left: 26px; }
|
|
332
400
|
.panel li { margin: 0 0 8px; }
|
|
333
401
|
.panel li:last-child { margin: 0; }
|
|
@@ -763,10 +831,12 @@ function buildIndicator(host, store, callbacks) {
|
|
|
763
831
|
.dot { animation: none; }
|
|
764
832
|
.toast, .note-popover, .resume-toast { animation: none; }
|
|
765
833
|
.resume-toast[data-leaving="true"] { opacity: 0; }
|
|
834
|
+
.anchor { transition: none; }
|
|
766
835
|
}
|
|
767
836
|
`;
|
|
768
837
|
const anchor = document.createElement("div");
|
|
769
838
|
anchor.className = "anchor";
|
|
839
|
+
store.keyboardWatcherCleanup = installKeyboardInsetWatcher(anchor);
|
|
770
840
|
const panel = document.createElement("div");
|
|
771
841
|
panel.className = "panel";
|
|
772
842
|
panel.hidden = true;
|
|
@@ -1923,6 +1993,7 @@ function userTest(options = {}) {
|
|
|
1923
1993
|
tasksPanelOpen: readTasksPanelOpen(),
|
|
1924
1994
|
outsidePointerHandler: null,
|
|
1925
1995
|
keydownHandler: null,
|
|
1996
|
+
keyboardWatcherCleanup: null,
|
|
1926
1997
|
hasMicPermission: false,
|
|
1927
1998
|
micAcquiring: true,
|
|
1928
1999
|
micFailReason: null,
|
|
@@ -2129,6 +2200,10 @@ function userTest(options = {}) {
|
|
|
2129
2200
|
document.removeEventListener("keydown", store.keydownHandler);
|
|
2130
2201
|
store.keydownHandler = null;
|
|
2131
2202
|
}
|
|
2203
|
+
if (store.keyboardWatcherCleanup) {
|
|
2204
|
+
store.keyboardWatcherCleanup();
|
|
2205
|
+
store.keyboardWatcherCleanup = null;
|
|
2206
|
+
}
|
|
2132
2207
|
for (const id of store.muteToastTimers) {
|
|
2133
2208
|
try {
|
|
2134
2209
|
window.clearTimeout(id);
|
|
@@ -2158,6 +2233,7 @@ var __test__ = {
|
|
|
2158
2233
|
classifyChunkResponse,
|
|
2159
2234
|
handleSessionClosed,
|
|
2160
2235
|
micChipState,
|
|
2236
|
+
computeKeyboardInset,
|
|
2161
2237
|
isStreamSilent,
|
|
2162
2238
|
rmsDbFromSamples,
|
|
2163
2239
|
SILENCE_RMS_DB_THRESHOLD,
|