shadok-ai 0.16.12 → 0.16.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/public/index.html +38 -8
package/package.json
CHANGED
package/public/index.html
CHANGED
|
@@ -350,8 +350,13 @@
|
|
|
350
350
|
display: block; margin-top: 3px; opacity: 0.8;
|
|
351
351
|
white-space: normal; line-height: 1.45;
|
|
352
352
|
}
|
|
353
|
+
/* Top banners sit ABOVE the header, not over it: they are flow items at the
|
|
354
|
+
very top of the fixed flex chassis (inserted as body's first child), so they
|
|
355
|
+
push the header and everything below down instead of overlapping it. A
|
|
356
|
+
`position:fixed; top:0` strip used to float over the header and hide the
|
|
357
|
+
brand/gauges underneath. */
|
|
353
358
|
#updateBanner {
|
|
354
|
-
|
|
359
|
+
flex: 0 0 auto; width: 100%; z-index: 1000;
|
|
355
360
|
background: var(--amber); color: var(--on-accent);
|
|
356
361
|
font-family: var(--sans); font-size: 12px; text-align: center;
|
|
357
362
|
padding: 6px 12px;
|
|
@@ -359,7 +364,7 @@
|
|
|
359
364
|
/* The re-login reminder (sign-in within 48h / expired). Same top strip as the
|
|
360
365
|
update banner; its own id so the two never share styling by accident. */
|
|
361
366
|
#expiryBanner {
|
|
362
|
-
|
|
367
|
+
flex: 0 0 auto; width: 100%; z-index: 1000;
|
|
363
368
|
background: var(--amber); color: var(--on-accent);
|
|
364
369
|
font-family: var(--sans); font-size: 12px;
|
|
365
370
|
padding: 6px 12px;
|
|
@@ -4562,8 +4567,10 @@
|
|
|
4562
4567
|
swapped = true;
|
|
4563
4568
|
restoring = true; // freezes pushChannels AND persistGroups (both bail on it)
|
|
4564
4569
|
const bar = document.createElement("div");
|
|
4570
|
+
// A flow strip at the very top (first child) so it sits ABOVE the header
|
|
4571
|
+
// rather than floating over it — same placement as the update/expiry banners.
|
|
4565
4572
|
bar.style.cssText =
|
|
4566
|
-
"
|
|
4573
|
+
"flex:0 0 auto;width:100%;z-index:99999;background:#b23b3b;color:#fff;" +
|
|
4567
4574
|
"padding:10px 14px;font:14px system-ui;text-align:center";
|
|
4568
4575
|
bar.textContent = "This cockpit was replaced by another instance on this port — reload to reconnect. ";
|
|
4569
4576
|
const btn = document.createElement("button");
|
|
@@ -4571,7 +4578,7 @@
|
|
|
4571
4578
|
btn.style.cssText = "margin-left:8px;padding:3px 10px;cursor:pointer";
|
|
4572
4579
|
btn.addEventListener("click", () => location.reload());
|
|
4573
4580
|
bar.appendChild(btn);
|
|
4574
|
-
document.body.
|
|
4581
|
+
document.body.insertBefore(bar, document.body.firstChild);
|
|
4575
4582
|
}
|
|
4576
4583
|
function pushChannels(list) {
|
|
4577
4584
|
if (restoring || swapped) return; // never overwrite the server list with a partial one, nor a foreign instance's
|
|
@@ -7674,7 +7681,8 @@
|
|
|
7674
7681
|
btn.textContent = "Re-login now";
|
|
7675
7682
|
btn.addEventListener("click", () => openAuthCard(true));
|
|
7676
7683
|
el.append(span, btn);
|
|
7677
|
-
|
|
7684
|
+
// First child → above the header in the flex chassis, not floating over it.
|
|
7685
|
+
document.body.insertBefore(el, document.body.firstChild);
|
|
7678
7686
|
}
|
|
7679
7687
|
// Expired is an escalation, not just a reminder — turn the strip red.
|
|
7680
7688
|
el.style.background = w.expired ? "var(--err)" : "";
|
|
@@ -7867,7 +7875,8 @@
|
|
|
7867
7875
|
if (!el) {
|
|
7868
7876
|
el = document.createElement("div");
|
|
7869
7877
|
el.id = "updateBanner";
|
|
7870
|
-
|
|
7878
|
+
// First child → above the header in the flex chassis, not floating over it.
|
|
7879
|
+
document.body.insertBefore(el, document.body.firstChild);
|
|
7871
7880
|
}
|
|
7872
7881
|
el.textContent = "Updating to v" + version + "… the page will reload automatically.";
|
|
7873
7882
|
}
|
|
@@ -7887,11 +7896,25 @@
|
|
|
7887
7896
|
// reloads onto the new build quickly instead of waiting out a backoff.
|
|
7888
7897
|
reloadExpectedUntil = Date.now() + 90_000;
|
|
7889
7898
|
break;
|
|
7890
|
-
case "history":
|
|
7899
|
+
case "history": {
|
|
7891
7900
|
// Full replay from the transcript (source of truth). Clear first so a
|
|
7892
7901
|
// reconnect (laptop wake / dropped link) rebuilds the transcript instead
|
|
7893
7902
|
// of appending a second copy of the whole history.
|
|
7894
|
-
|
|
7903
|
+
//
|
|
7904
|
+
// Hold the reader's place across the wipe+rebuild. On a RECONNECT the
|
|
7905
|
+
// transcript already carries the conversation, and tearing it down to
|
|
7906
|
+
// rebuild it snaps the view to the top UNLESS the browser's scroll
|
|
7907
|
+
// anchoring happens to save us — which it does not when the tab was in
|
|
7908
|
+
// the background while the replay ran (anchoring needs a live layout),
|
|
7909
|
+
// and does not in Safari. That is the reported "the chat jumps back up
|
|
7910
|
+
// when I come back". The replay is the same messages in the same order,
|
|
7911
|
+
// appended bottom-first, so we restore deterministically: pinned to the
|
|
7912
|
+
// bottom if they were following live, otherwise holding the same
|
|
7913
|
+
// distance from the bottom so what they were reading stays in view.
|
|
7914
|
+
const el = t.transcriptEl;
|
|
7915
|
+
const wasStick = el._stickBottom !== false;
|
|
7916
|
+
const fromBottom = Math.max(0, el.scrollHeight - el.scrollTop - el.clientHeight);
|
|
7917
|
+
el.innerHTML = "";
|
|
7895
7918
|
t.unreadSep = null; // the separator element went with the wipe
|
|
7896
7919
|
addTurn(t, "system", "", "— resumed session history —");
|
|
7897
7920
|
for (const h of msg.turns) {
|
|
@@ -7923,7 +7946,14 @@
|
|
|
7923
7946
|
if (h.afterInternal) b.parentElement.classList.add("after-gap");
|
|
7924
7947
|
}
|
|
7925
7948
|
}
|
|
7949
|
+
// Restore the reader's place deterministically — never trust the
|
|
7950
|
+
// browser's implicit scroll anchoring for a full teardown.
|
|
7951
|
+
el._stickBottom = wasStick;
|
|
7952
|
+
el.scrollTop = wasStick
|
|
7953
|
+
? el.scrollHeight
|
|
7954
|
+
: Math.max(0, el.scrollHeight - el.clientHeight - fromBottom);
|
|
7926
7955
|
break;
|
|
7956
|
+
}
|
|
7927
7957
|
case "ready":
|
|
7928
7958
|
// The server just named the instance it is. If it's not the one this
|
|
7929
7959
|
// page was loaded from, the port was taken over — stop writing, prompt a
|