shadok-ai 0.2.60 → 0.2.62
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 +60 -4
package/package.json
CHANGED
package/public/index.html
CHANGED
|
@@ -335,6 +335,11 @@
|
|
|
335
335
|
/* The star lives in the header pill on desktop; its menu twin appears only on
|
|
336
336
|
a phone (see the mobile query). */
|
|
337
337
|
#starMenuItem { display: none; }
|
|
338
|
+
/* Overflowed header icons, shown as a compact row at the top of the menu.
|
|
339
|
+
Hidden entirely when nothing overflowed. */
|
|
340
|
+
.mm-tools { display: flex; flex-wrap: wrap; gap: 4px; padding-bottom: 4px; margin-bottom: 2px; border-bottom: 1px solid var(--line); }
|
|
341
|
+
.mm-tools:empty { display: none; }
|
|
342
|
+
#moreMenu .mm-tools button { width: auto; } /* override #moreMenu button width:100% */
|
|
338
343
|
#moreMenu .mm-sep { height: 1px; background: var(--line); margin: 4px 2px; }
|
|
339
344
|
#moreMenu .mm-label { padding: 2px 4px; font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-dim); }
|
|
340
345
|
.mm-themes { display: flex; gap: 6px; padding: 2px 4px 4px; }
|
|
@@ -1087,10 +1092,11 @@
|
|
|
1087
1092
|
#chanBar .gauge .label { display: none; } /* valeurs seules, plus compact */
|
|
1088
1093
|
#chanBar { gap: 6px; padding: 6px 10px; }
|
|
1089
1094
|
header { flex-wrap: wrap; row-gap: 6px; gap: 8px; padding: 8px 12px; }
|
|
1090
|
-
/*
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1095
|
+
/* One header row: brand + dials + as many tool icons as fit. The spacer that
|
|
1096
|
+
right-aligns them on desktop is dropped so they pack left; whatever doesn't
|
|
1097
|
+
fit is moved into the ⋯ menu by reflowHeaderTools (JS). .hdr-tools keeps
|
|
1098
|
+
its base `display: contents`, so the icons stay direct header flex items. */
|
|
1099
|
+
header .spacer { display: none; }
|
|
1094
1100
|
header button.icon { padding: 5px 7px; }
|
|
1095
1101
|
/* The star pill is the widest tool and would push an icon off the row; on a
|
|
1096
1102
|
phone it moves into the ⋯ menu (#starMenuItem) instead. */
|
|
@@ -1451,6 +1457,10 @@
|
|
|
1451
1457
|
<div class="more-wrap">
|
|
1452
1458
|
<button id="moreBtn" class="icon" title="More">⋯</button>
|
|
1453
1459
|
<div id="moreMenu" hidden>
|
|
1460
|
+
<!-- Header tool icons that didn't fit the row are moved here by
|
|
1461
|
+
reflowHeaderTools (the real buttons, so their handlers come along).
|
|
1462
|
+
Empty — and hidden — whenever everything fits. -->
|
|
1463
|
+
<div id="overflowTools" class="mm-tools"></div>
|
|
1454
1464
|
<button id="toggleDiff">Diff</button>
|
|
1455
1465
|
<button id="tourReplay">Guided tour</button>
|
|
1456
1466
|
<!-- On a phone the header star pill is dropped (it's the widest tool, and
|
|
@@ -2903,6 +2913,7 @@
|
|
|
2903
2913
|
if (brandName && !brandName.isContentEditable) brandName.textContent = cockpitTitle || "shadok-ai";
|
|
2904
2914
|
titleBase = cockpitTitle || BASE_TITLE;
|
|
2905
2915
|
paint(); // re-stamp document.title (with any notification badge)
|
|
2916
|
+
if (typeof scheduleReflow === "function") scheduleReflow(); // name width changed
|
|
2906
2917
|
}
|
|
2907
2918
|
|
|
2908
2919
|
// ── Colour palette: per instance, persisted server-side (like the name) ──
|
|
@@ -4821,6 +4832,46 @@
|
|
|
4821
4832
|
window.open("https://github.com/shadok-ai/shadok-ai", "_blank", "noopener");
|
|
4822
4833
|
});
|
|
4823
4834
|
|
|
4835
|
+
// ── Header tool overflow ─────────────────────────────────────────────
|
|
4836
|
+
// The header is one row: brand + dials + as many tool icons as fit. Any icon
|
|
4837
|
+
// that would push the ⋯ button onto a second line is moved INTO the ⋯ menu —
|
|
4838
|
+
// the real button element, so its click handler travels with it. Desktop has
|
|
4839
|
+
// room for them all. Recomputed on load, on resize, and when the name changes.
|
|
4840
|
+
const OVERFLOW_TOOLS = ["secretsBtn", "profilesBtn", "telegramBtn", "muteNotif"];
|
|
4841
|
+
function reflowHeaderTools() {
|
|
4842
|
+
const hdrTools = document.querySelector(".hdr-tools");
|
|
4843
|
+
const moreWrap = document.querySelector(".more-wrap");
|
|
4844
|
+
const moreBtn = $("moreBtn");
|
|
4845
|
+
const overflow = $("overflowTools");
|
|
4846
|
+
const brand = $("brandName");
|
|
4847
|
+
if (!hdrTools || !moreWrap || !moreBtn || !overflow || !brand) return;
|
|
4848
|
+
// 1. Reset: every tool back in the header, in the declared order.
|
|
4849
|
+
for (const id of OVERFLOW_TOOLS) {
|
|
4850
|
+
const el = $(id);
|
|
4851
|
+
if (el) hdrTools.insertBefore(el, moreWrap);
|
|
4852
|
+
}
|
|
4853
|
+
// 2. Only a narrow screen needs to shed icons.
|
|
4854
|
+
if (!matchMedia("(max-width: 640px)").matches) return;
|
|
4855
|
+
// 3. Move icons from the end into the menu until ⋯ is back on the first row.
|
|
4856
|
+
// Two rows → ⋯ sits a line-height below the brand; the 8px threshold
|
|
4857
|
+
// ignores sub-pixel jitter.
|
|
4858
|
+
const rowTop = () => brand.getBoundingClientRect().top;
|
|
4859
|
+
for (let i = OVERFLOW_TOOLS.length - 1; i >= 0; i--) {
|
|
4860
|
+
if (moreBtn.getBoundingClientRect().top - rowTop() < 8) break; // it fits now
|
|
4861
|
+
const el = $(OVERFLOW_TOOLS[i]);
|
|
4862
|
+
if (el) overflow.insertBefore(el, overflow.firstChild); // keep original order
|
|
4863
|
+
}
|
|
4864
|
+
}
|
|
4865
|
+
let reflowPending = false;
|
|
4866
|
+
function scheduleReflow() {
|
|
4867
|
+
if (reflowPending) return;
|
|
4868
|
+
reflowPending = true;
|
|
4869
|
+
requestAnimationFrame(() => { reflowPending = false; reflowHeaderTools(); });
|
|
4870
|
+
}
|
|
4871
|
+
window.addEventListener("resize", scheduleReflow);
|
|
4872
|
+
document.addEventListener("DOMContentLoaded", reflowHeaderTools);
|
|
4873
|
+
reflowHeaderTools();
|
|
4874
|
+
|
|
4824
4875
|
// ── Diff panel ──────────────────────────────────────────
|
|
4825
4876
|
function colorDiff(text) {
|
|
4826
4877
|
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
@@ -5596,6 +5647,11 @@
|
|
|
5596
5647
|
}
|
|
5597
5648
|
if (r && r.ok) {
|
|
5598
5649
|
$("authCode").value = "";
|
|
5650
|
+
// The login just wrote the OAuth credentials the usage gauges read from
|
|
5651
|
+
// (src/usage.ts, live-first). Repaint them now — otherwise a freshly
|
|
5652
|
+
// signed-in instance shows blank dials until the next 60s poll, which
|
|
5653
|
+
// reads as "usage is broken" right after onboarding.
|
|
5654
|
+
refreshUsage();
|
|
5599
5655
|
// Name the account: a machine can serve several people, and "signed in"
|
|
5600
5656
|
// without saying as whom is the kind of detail that costs an hour later.
|
|
5601
5657
|
let who = "";
|