@iasiv5/dsh-quota-watch 0.1.28 → 0.1.29

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 CHANGED
@@ -198,7 +198,7 @@ function parseInset(computedValue) {
198
198
 
199
199
  // src/client.mjs
200
200
  var name = "quota-watch-client";
201
- var inject = [];
201
+ var inject = ["slots"];
202
202
  var CARD_SELECTOR = "[data-dsh-quota-watch-card]";
203
203
  var FLOAT_SELECTOR = "[data-dsh-quota-watch-float]";
204
204
  var FETCH_TIMEOUT_MS = 15e3;
@@ -655,7 +655,10 @@ function mountQuotaCard({
655
655
  retryBackoff = 2,
656
656
  // Q16: a confirmed SUCCESS notice lingers about five seconds before the
657
657
  // panel returns to the latest inventory. Injectable for tests.
658
- outcomeNoticeMs = 5e3
658
+ outcomeNoticeMs = 5e3,
659
+ // Shell-takeover sentinel (2026-10-13 ds-bot): inject `ctx.slots` to arm it.
660
+ // Injectable so DOM tests and exotic hosts keep the legacy behavior.
661
+ slots = null
659
662
  } = {}) {
660
663
  if (!doc?.body || typeof fetchImpl !== "function") return () => {
661
664
  };
@@ -1459,12 +1462,22 @@ function mountQuotaCard({
1459
1462
  let currentFoot = null;
1460
1463
  let footTooNarrow = false;
1461
1464
  let noDataHidden = false;
1465
+ let shellTakeover = false;
1466
+ const syncShellTakeover = () => {
1467
+ try {
1468
+ shellTakeover = (slots?.entries?.("sidebar.workspaces") ?? []).some(
1469
+ (entry) => (entry.options.priority ?? 0) < 0
1470
+ );
1471
+ } catch {
1472
+ shellTakeover = false;
1473
+ }
1474
+ };
1462
1475
  const syncFootNarrowness = () => {
1463
1476
  footTooNarrow = currentFoot !== null && currentFoot.clientWidth > 0 && currentFoot.clientWidth < CARD_MIN_WIDTH;
1464
1477
  };
1465
1478
  const syncCardVisibility = () => {
1466
1479
  syncFootNarrowness();
1467
- const showCard = !surfaceFlags.cardHidden && !footTooNarrow && !noDataHidden;
1480
+ const showCard = !surfaceFlags.cardHidden && !footTooNarrow && !noDataHidden && !shellTakeover;
1468
1481
  container.hidden = !showCard;
1469
1482
  card.style.display = showCard ? "" : "none";
1470
1483
  };
@@ -1574,6 +1587,18 @@ function mountQuotaCard({
1574
1587
  if (!disposed) renderAll();
1575
1588
  }) : null;
1576
1589
  langObserver?.observe(doc.documentElement, { attributeFilter: ["lang"] });
1590
+ let offShellTakeover = null;
1591
+ try {
1592
+ if (slots && typeof slots.subscribe === "function") {
1593
+ offShellTakeover = slots.subscribe("sidebar.workspaces", () => {
1594
+ if (disposed) return;
1595
+ syncShellTakeover();
1596
+ syncCardVisibility();
1597
+ });
1598
+ }
1599
+ } catch {
1600
+ }
1601
+ syncShellTakeover();
1577
1602
  syncFloatVisibility();
1578
1603
  place();
1579
1604
  const nextPollDelay = () => {
@@ -1721,6 +1746,7 @@ function mountQuotaCard({
1721
1746
  outcomeNoticeTimer = void 0;
1722
1747
  observer.disconnect();
1723
1748
  langObserver?.disconnect();
1749
+ if (offShellTakeover) offShellTakeover();
1724
1750
  doc.removeEventListener("visibilitychange", onVisibilityChange);
1725
1751
  doc.removeEventListener("pointerdown", onDocPointerDown, true);
1726
1752
  doc.removeEventListener("scroll", onDocScroll, true);
@@ -1739,7 +1765,7 @@ function mountQuotaCard({
1739
1765
  };
1740
1766
  }
1741
1767
  function apply(ctx) {
1742
- ctx.effect(() => mountQuotaCard(), "dsh-quota-watch: sidebar");
1768
+ ctx.effect(() => mountQuotaCard({ slots: ctx.slots ?? null }), "dsh-quota-watch: sidebar");
1743
1769
  }
1744
1770
 
1745
1771
  return module.exports;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iasiv5/dsh-quota-watch",
3
- "version": "0.1.28",
3
+ "version": "0.1.29",
4
4
  "description": "DSH Web sidebar monitor for GLM Coding Plan quotas and GitHub Copilot credits",
5
5
  "type": "module",
6
6
  "main": "./src/host.mjs",
@@ -49,7 +49,9 @@
49
49
  },
50
50
  "client": {
51
51
  "platform": "web",
52
- "inject": []
52
+ "inject": [
53
+ "slots"
54
+ ]
53
55
  }
54
56
  },
55
57
  "scripts": {
package/src/client.mjs CHANGED
@@ -5,7 +5,12 @@ import { MARGIN, clampPoint, loadFloatPosition, loadSurfaceFlags, saveFloatPosit
5
5
  import { DRAG_SLOP_MOUSE, DRAG_SLOP_TOUCH, parseInset, clampFrame, dragSlop, grabOffset } from './client/drag.mjs'
6
6
 
7
7
  export const name = 'quota-watch-client'
8
- export const inject = []
8
+ // 2026-10-13: the shell-takeover sentinel reads the OFFICIAL slots ledger, so
9
+ // the client now touches ctx.slots — cordis denies undeclared service access
10
+ // ("cannot get property 'slots' without inject") and the whole activation
11
+ // dies. Declare BEFORE using; the bundle + package.json dsh.client.inject
12
+ // must stay in lockstep (locked by tests/package-shape.test.mjs).
13
+ export const inject = ['slots']
9
14
 
10
15
  const CARD_SELECTOR = '[data-dsh-quota-watch-card]'
11
16
  const FLOAT_SELECTOR = '[data-dsh-quota-watch-float]'
@@ -556,6 +561,9 @@ export function mountQuotaCard({
556
561
  // Q16: a confirmed SUCCESS notice lingers about five seconds before the
557
562
  // panel returns to the latest inventory. Injectable for tests.
558
563
  outcomeNoticeMs = 5_000,
564
+ // Shell-takeover sentinel (2026-10-13 ds-bot): inject `ctx.slots` to arm it.
565
+ // Injectable so DOM tests and exotic hosts keep the legacy behavior.
566
+ slots = null,
559
567
  } = {}) {
560
568
  if (!doc?.body || typeof fetchImpl !== 'function') return () => {}
561
569
  if (doc.querySelector(CARD_SELECTOR) || doc.querySelector(FLOAT_SELECTOR)) return () => {}
@@ -1552,6 +1560,23 @@ export function mountQuotaCard({
1552
1560
  let currentFoot = null
1553
1561
  let footTooNarrow = false
1554
1562
  let noDataHidden = false
1563
+ // The sidebar foot belongs to whoever registers sidebar.workspaces
1564
+ // (ui-sidebar doc: "the foot is the sidebar.workspaces registrant's"). The
1565
+ // official workspace tree registers at default priority 0 (ui-workspace); a
1566
+ // NEGATIVE-priority occupant is a takeover shell (ds-bot takes the seat at
1567
+ // -10 for its native bot sidebar) — while one is live the injected card
1568
+ // yields the whole foot, same contract as the dsh-skins/dsh-m footer rows.
1569
+ // The signal is the OFFICIAL slot ledger, not any ds-bot internal.
1570
+ let shellTakeover = false
1571
+ const syncShellTakeover = () => {
1572
+ try {
1573
+ shellTakeover = (slots?.entries?.('sidebar.workspaces') ?? []).some(
1574
+ (entry) => (entry.options.priority ?? 0) < 0,
1575
+ )
1576
+ } catch {
1577
+ shellTakeover = false
1578
+ }
1579
+ }
1555
1580
  const syncFootNarrowness = () => {
1556
1581
  footTooNarrow = currentFoot !== null && currentFoot.clientWidth > 0 && currentFoot.clientWidth < CARD_MIN_WIDTH
1557
1582
  }
@@ -1564,7 +1589,7 @@ export function mountQuotaCard({
1564
1589
  // The sidebar card shows ONLY in an expanded sidebar: the width guard hides
1565
1590
  // it in narrow rails / squeezed containers (works on every profile), and no
1566
1591
  // host collapse signal is consulted at all (they proved host-specific).
1567
- const showCard = !surfaceFlags.cardHidden && !footTooNarrow && !noDataHidden
1592
+ const showCard = !surfaceFlags.cardHidden && !footTooNarrow && !noDataHidden && !shellTakeover
1568
1593
  container.hidden = !showCard
1569
1594
  card.style.display = showCard ? '' : 'none'
1570
1595
  }
@@ -1696,6 +1721,21 @@ export function mountQuotaCard({
1696
1721
  ? new win.MutationObserver(() => { if (!disposed) renderAll() })
1697
1722
  : null
1698
1723
  langObserver?.observe(doc.documentElement, { attributeFilter: ['lang'] })
1724
+ // Arm the shell-takeover sentinel: re-probe on every workspaces-ledger
1725
+ // mutation (microtask-batched by the slot core) and once up front. Without
1726
+ // an injected slots service (DOM tests, exotic hosts) this is a no-op and
1727
+ // the card behaves exactly as before.
1728
+ let offShellTakeover = null
1729
+ try {
1730
+ if (slots && typeof slots.subscribe === 'function') {
1731
+ offShellTakeover = slots.subscribe('sidebar.workspaces', () => {
1732
+ if (disposed) return
1733
+ syncShellTakeover()
1734
+ syncCardVisibility()
1735
+ })
1736
+ }
1737
+ } catch {}
1738
+ syncShellTakeover()
1699
1739
  // Cold until data lands: keep the shell hidden so a slow or failed first
1700
1740
  // probe never flashes an empty capsule (startPolling arms the retry chain).
1701
1741
  syncFloatVisibility()
@@ -1870,6 +1910,7 @@ export function mountQuotaCard({
1870
1910
  outcomeNoticeTimer = undefined
1871
1911
  observer.disconnect()
1872
1912
  langObserver?.disconnect()
1913
+ if (offShellTakeover) offShellTakeover()
1873
1914
  doc.removeEventListener('visibilitychange', onVisibilityChange)
1874
1915
  doc.removeEventListener('pointerdown', onDocPointerDown, true)
1875
1916
  doc.removeEventListener('scroll', onDocScroll, true)
@@ -1890,5 +1931,5 @@ export function mountQuotaCard({
1890
1931
  }
1891
1932
 
1892
1933
  export function apply(ctx) {
1893
- ctx.effect(() => mountQuotaCard(), 'dsh-quota-watch: sidebar')
1934
+ ctx.effect(() => mountQuotaCard({ slots: ctx.slots ?? null }), 'dsh-quota-watch: sidebar')
1894
1935
  }