@artenx/dshb 0.1.25 → 0.1.26
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/lib/client.js +114 -44
- package/lib/client.js.map +1 -1
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -1516,7 +1516,8 @@ window.__ModuleLoader__.load({
|
|
|
1516
1516
|
document.querySelectorAll(`[${FRAME_ATTR}="stats"]`).forEach((el) => {
|
|
1517
1517
|
if (!el.isConnected || !STATS_LINE_RE.test((el.textContent ?? "").trim())) el.removeAttribute(FRAME_ATTR);
|
|
1518
1518
|
});
|
|
1519
|
-
const
|
|
1519
|
+
const scope = document.querySelector("[class*=\"composerStack\"]") ?? document.querySelector("[class*=\"composer\"]") ?? document;
|
|
1520
|
+
const cands = Array.from(scope.querySelectorAll("span, div")).filter((el) => {
|
|
1520
1521
|
if (!isStatsText(el)) return false;
|
|
1521
1522
|
if (getComputedStyle(el).display === "contents") return false;
|
|
1522
1523
|
return true;
|
|
@@ -1538,15 +1539,22 @@ window.__ModuleLoader__.load({
|
|
|
1538
1539
|
}
|
|
1539
1540
|
};
|
|
1540
1541
|
mark();
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1542
|
+
let raf = 0;
|
|
1543
|
+
const scheduleMark = () => {
|
|
1544
|
+
if (raf !== 0 || !narrow.matches) return;
|
|
1545
|
+
raf = requestAnimationFrame(() => {
|
|
1546
|
+
raf = 0;
|
|
1547
|
+
mark();
|
|
1548
|
+
});
|
|
1549
|
+
};
|
|
1550
|
+
const mo = new MutationObserver(scheduleMark);
|
|
1544
1551
|
mo.observe(document.documentElement, {
|
|
1545
1552
|
childList: true,
|
|
1546
1553
|
subtree: true
|
|
1547
1554
|
});
|
|
1548
1555
|
narrow.addEventListener("change", mark);
|
|
1549
1556
|
return () => {
|
|
1557
|
+
if (raf !== 0) cancelAnimationFrame(raf);
|
|
1550
1558
|
mo.disconnect();
|
|
1551
1559
|
narrow.removeEventListener("change", mark);
|
|
1552
1560
|
};
|
|
@@ -1566,36 +1574,54 @@ window.__ModuleLoader__.load({
|
|
|
1566
1574
|
"overflow-y",
|
|
1567
1575
|
"box-sizing"
|
|
1568
1576
|
];
|
|
1577
|
+
/** 幂等写入 important 内联样式:值未变化时跳过,避免 MutationObserver(attributes) 自触发循环。 */
|
|
1578
|
+
function setImportantIfChanged(el, prop, value) {
|
|
1579
|
+
if (el.style.getPropertyValue(prop) === value && el.style.getPropertyPriority(prop) === "important") return;
|
|
1580
|
+
el.style.setProperty(prop, value, "important");
|
|
1581
|
+
}
|
|
1582
|
+
/** 当前视口下的可视区域(手机键盘弹出时 visualViewport 与布局视口错位)。 */
|
|
1583
|
+
function visibleViewport() {
|
|
1584
|
+
const vv = window.visualViewport;
|
|
1585
|
+
if (vv) return {
|
|
1586
|
+
vw: vv.width,
|
|
1587
|
+
vh: vv.offsetTop + vv.height,
|
|
1588
|
+
top: vv.offsetTop
|
|
1589
|
+
};
|
|
1590
|
+
return {
|
|
1591
|
+
vw: window.innerWidth,
|
|
1592
|
+
vh: window.innerHeight,
|
|
1593
|
+
top: 0
|
|
1594
|
+
};
|
|
1595
|
+
}
|
|
1569
1596
|
/** Keep the model menu anchored to its trigger while fitting it in the viewport. */
|
|
1570
1597
|
function positionAnchoredMenu(el, triggerRect, maxWidth, maxHeight) {
|
|
1571
1598
|
const margin = 8;
|
|
1572
|
-
const vw =
|
|
1573
|
-
|
|
1574
|
-
el
|
|
1575
|
-
el
|
|
1576
|
-
el
|
|
1577
|
-
el
|
|
1578
|
-
el
|
|
1579
|
-
el
|
|
1580
|
-
el
|
|
1581
|
-
el
|
|
1582
|
-
el
|
|
1583
|
-
el.style.setProperty("overflow-y", "auto", "important");
|
|
1599
|
+
const { vw, vh } = visibleViewport();
|
|
1600
|
+
setImportantIfChanged(el, "position", "fixed");
|
|
1601
|
+
setImportantIfChanged(el, "box-sizing", "border-box");
|
|
1602
|
+
setImportantIfChanged(el, "left", "0");
|
|
1603
|
+
setImportantIfChanged(el, "right", "auto");
|
|
1604
|
+
setImportantIfChanged(el, "top", "0");
|
|
1605
|
+
setImportantIfChanged(el, "bottom", "auto");
|
|
1606
|
+
setImportantIfChanged(el, "min-width", "0");
|
|
1607
|
+
setImportantIfChanged(el, "max-width", `${Math.max(0, Math.min(maxWidth, vw - 16))}px`);
|
|
1608
|
+
setImportantIfChanged(el, "max-height", `${Math.max(0, Math.min(maxHeight, vh - 16))}px`);
|
|
1609
|
+
setImportantIfChanged(el, "overflow-y", "auto");
|
|
1584
1610
|
let width = el.offsetWidth;
|
|
1585
1611
|
let height = el.offsetHeight;
|
|
1586
|
-
const
|
|
1612
|
+
const { top: viewportTop } = visibleViewport();
|
|
1613
|
+
const spaceAbove = Math.max(0, triggerRect.top - viewportTop - 16);
|
|
1587
1614
|
const spaceBelow = Math.max(0, vh - triggerRect.bottom - 16);
|
|
1588
1615
|
const expandUp = height <= spaceAbove || spaceAbove >= spaceBelow;
|
|
1589
1616
|
const available = expandUp ? spaceAbove : spaceBelow;
|
|
1590
1617
|
if (height > available) {
|
|
1591
|
-
el
|
|
1618
|
+
setImportantIfChanged(el, "max-height", `${Math.max(0, available - margin)}px`);
|
|
1592
1619
|
height = el.offsetHeight;
|
|
1593
1620
|
width = el.offsetWidth;
|
|
1594
1621
|
}
|
|
1595
1622
|
const top = expandUp ? triggerRect.top - margin - height : triggerRect.bottom + margin;
|
|
1596
|
-
|
|
1597
|
-
el
|
|
1598
|
-
el.style.setProperty("top", `${Math.max(margin, Math.min(top, vh - height - margin))}px`, "important");
|
|
1623
|
+
setImportantIfChanged(el, "left", `${Math.max(margin, Math.min(triggerRect.right - width, vw - width - margin))}px`);
|
|
1624
|
+
setImportantIfChanged(el, "top", `${Math.max(viewportTop + margin, Math.min(top, vh - height - margin))}px`);
|
|
1599
1625
|
}
|
|
1600
1626
|
/**
|
|
1601
1627
|
* 模型名多为纯连字符词(DeepSeek-V4-Flash-Vision-Exp);white-space:normal 下
|
|
@@ -1664,9 +1690,13 @@ window.__ModuleLoader__.load({
|
|
|
1664
1690
|
function installModelMenuPosition(ctx) {
|
|
1665
1691
|
ctx.effect(() => {
|
|
1666
1692
|
const narrow = window.matchMedia(NARROW_QUERY);
|
|
1693
|
+
let fallbackLast = 0;
|
|
1667
1694
|
const findMenus = () => {
|
|
1668
1695
|
const byHash = Array.from(document.querySelectorAll("[class*=\"7KE1Ra_menu\"]"));
|
|
1669
1696
|
if (byHash.length > 0) return byHash;
|
|
1697
|
+
const now = Date.now();
|
|
1698
|
+
if (now - fallbackLast < 500) return [];
|
|
1699
|
+
fallbackLast = now;
|
|
1670
1700
|
return Array.from(document.querySelectorAll("[class*=\"_menu\"]")).filter((el) => el.querySelector("[class*=\"cellLabel\"], [class*=\"modelName\"]") !== null);
|
|
1671
1701
|
};
|
|
1672
1702
|
const findTrigger = (menu) => {
|
|
@@ -1727,16 +1757,42 @@ window.__ModuleLoader__.load({
|
|
|
1727
1757
|
const mo = new MutationObserver(() => requestAnimationFrame(sync));
|
|
1728
1758
|
mo.observe(document.documentElement, {
|
|
1729
1759
|
childList: true,
|
|
1730
|
-
subtree: true
|
|
1760
|
+
subtree: true,
|
|
1761
|
+
attributes: true,
|
|
1762
|
+
attributeFilter: ["style"]
|
|
1731
1763
|
});
|
|
1732
1764
|
narrow.addEventListener("change", sync);
|
|
1733
1765
|
window.addEventListener("resize", sync);
|
|
1734
1766
|
window.addEventListener("scroll", sync, true);
|
|
1767
|
+
window.visualViewport?.addEventListener("resize", sync);
|
|
1768
|
+
window.visualViewport?.addEventListener("scroll", sync);
|
|
1769
|
+
let lastPointerTarget = null;
|
|
1770
|
+
const keyboardLikelyOpen = () => {
|
|
1771
|
+
const vv = window.visualViewport;
|
|
1772
|
+
if (!vv) return false;
|
|
1773
|
+
return window.innerHeight - vv.height > 150;
|
|
1774
|
+
};
|
|
1775
|
+
const onPointerDown = (event) => {
|
|
1776
|
+
lastPointerTarget = event.target instanceof Element ? event.target : null;
|
|
1777
|
+
};
|
|
1778
|
+
const onFocusIn = (event) => {
|
|
1779
|
+
if (!narrow.matches || !(event.target instanceof Element) || keyboardLikelyOpen()) return;
|
|
1780
|
+
const input = event.target.closest("input");
|
|
1781
|
+
if (!input || input.closest("[class*=\"7KE1Ra_menu\"], [class*=\"_menu\"]") === null) return;
|
|
1782
|
+
if (lastPointerTarget !== null && (lastPointerTarget === input || input.contains(lastPointerTarget))) return;
|
|
1783
|
+
input.blur();
|
|
1784
|
+
};
|
|
1785
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
1786
|
+
document.addEventListener("focusin", onFocusIn, true);
|
|
1735
1787
|
return () => {
|
|
1736
1788
|
mo.disconnect();
|
|
1737
1789
|
narrow.removeEventListener("change", sync);
|
|
1738
1790
|
window.removeEventListener("resize", sync);
|
|
1739
1791
|
window.removeEventListener("scroll", sync, true);
|
|
1792
|
+
window.visualViewport?.removeEventListener("resize", sync);
|
|
1793
|
+
window.visualViewport?.removeEventListener("scroll", sync);
|
|
1794
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
1795
|
+
document.removeEventListener("focusin", onFocusIn, true);
|
|
1740
1796
|
};
|
|
1741
1797
|
}, "dshb-mobile: model menu position");
|
|
1742
1798
|
}
|
|
@@ -1757,20 +1813,22 @@ window.__ModuleLoader__.load({
|
|
|
1757
1813
|
const rootRect = root.getBoundingClientRect();
|
|
1758
1814
|
if (rootRect.width === 0 && rootRect.height === 0) continue;
|
|
1759
1815
|
const gap = 8;
|
|
1760
|
-
panel
|
|
1761
|
-
panel
|
|
1762
|
-
panel
|
|
1763
|
-
panel
|
|
1764
|
-
panel
|
|
1765
|
-
panel
|
|
1766
|
-
panel
|
|
1816
|
+
setImportantIfChanged(panel, "position", "fixed");
|
|
1817
|
+
setImportantIfChanged(panel, "top", "auto");
|
|
1818
|
+
setImportantIfChanged(panel, "bottom", `${window.innerHeight - rootRect.top + gap}px`);
|
|
1819
|
+
setImportantIfChanged(panel, "left", "auto");
|
|
1820
|
+
setImportantIfChanged(panel, "right", `${Math.max(gap, window.innerWidth - rootRect.right)}px`);
|
|
1821
|
+
setImportantIfChanged(panel, "max-height", `${Math.max(160, rootRect.top - 16)}px`);
|
|
1822
|
+
setImportantIfChanged(panel, "overflow-y", "auto");
|
|
1767
1823
|
}
|
|
1768
1824
|
};
|
|
1769
1825
|
sync();
|
|
1770
1826
|
const mo = new MutationObserver(() => requestAnimationFrame(sync));
|
|
1771
1827
|
mo.observe(document.documentElement, {
|
|
1772
1828
|
childList: true,
|
|
1773
|
-
subtree: true
|
|
1829
|
+
subtree: true,
|
|
1830
|
+
attributes: true,
|
|
1831
|
+
attributeFilter: ["style"]
|
|
1774
1832
|
});
|
|
1775
1833
|
narrow.addEventListener("change", sync);
|
|
1776
1834
|
window.addEventListener("resize", sync);
|
|
@@ -2112,7 +2170,14 @@ window.__ModuleLoader__.load({
|
|
|
2112
2170
|
}
|
|
2113
2171
|
}
|
|
2114
2172
|
};
|
|
2115
|
-
|
|
2173
|
+
let raf = 0;
|
|
2174
|
+
new MutationObserver(() => {
|
|
2175
|
+
if (raf !== 0) return;
|
|
2176
|
+
raf = requestAnimationFrame(() => {
|
|
2177
|
+
raf = 0;
|
|
2178
|
+
scan();
|
|
2179
|
+
});
|
|
2180
|
+
}).observe(document.body, {
|
|
2116
2181
|
childList: true,
|
|
2117
2182
|
subtree: true
|
|
2118
2183
|
});
|
|
@@ -4651,20 +4716,25 @@ window.__ModuleLoader__.load({
|
|
|
4651
4716
|
"认证": "auth",
|
|
4652
4717
|
"工作节点": "dshb-nodes"
|
|
4653
4718
|
};
|
|
4719
|
+
let raf = 0;
|
|
4654
4720
|
new MutationObserver(() => {
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4658
|
-
|
|
4659
|
-
const
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4721
|
+
if (raf !== 0) return;
|
|
4722
|
+
raf = requestAnimationFrame(() => {
|
|
4723
|
+
raf = 0;
|
|
4724
|
+
const cells = document.querySelectorAll("button[class*=\"navCell\"]");
|
|
4725
|
+
for (const cell of Array.from(cells)) {
|
|
4726
|
+
const label = cell.querySelector("span[class*=\"navLabel\"]");
|
|
4727
|
+
if (!label) continue;
|
|
4728
|
+
const text = label.textContent ?? "";
|
|
4729
|
+
const iconKey = ICON_LABELS[text];
|
|
4730
|
+
if (!iconKey) continue;
|
|
4731
|
+
const iconSlot = cell.querySelector("[class*=\"navIcon\"]");
|
|
4732
|
+
if (!iconSlot) continue;
|
|
4733
|
+
if (iconSlot.getAttribute("data-dshb-icon") === iconKey) continue;
|
|
4734
|
+
iconSlot.innerHTML = ICON_SVG[iconKey] ?? "";
|
|
4735
|
+
iconSlot.setAttribute("data-dshb-icon", iconKey);
|
|
4736
|
+
}
|
|
4737
|
+
});
|
|
4668
4738
|
}).observe(document.body, {
|
|
4669
4739
|
childList: true,
|
|
4670
4740
|
subtree: true
|