dsh-taskboard 0.4.3 → 0.4.4
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/README.md +7 -0
- package/lib/client.js +44 -9
- package/package.json +1 -1
- package/src/client/index.ts +10 -0
- package/src/client/styles.ts +41 -8
- package/src/shared/version.ts +1 -1
package/README.md
CHANGED
|
@@ -213,6 +213,13 @@ node scripts/screenshot.mjs # 重新生成 img/ 截图(需本机 Edge)
|
|
|
213
213
|
|
|
214
214
|
## 升级日志
|
|
215
215
|
|
|
216
|
+
### 0.4.4
|
|
217
|
+
|
|
218
|
+
- **修复看板偶尔突然掉样式的问题([ #3](https://github.com/cloader/dsh-taskboard/issues/3))**。排查结论:浏览器里其他插件在后台热更新时,会按"样式归属"做清理,而看板自己的样式表没有归属标记,被误当成别的插件的样式连带删掉了。本次修复后:
|
|
219
|
+
- 看板的样式表明确打上了自己的归属标记,其他插件更新时不会再误删它
|
|
220
|
+
- 看板每 2 秒自动检查一次样式是否完好,即便被误删也会立刻自动恢复——以后遇到掉样式,最多闪一下就自动修好,不用再刷新页面
|
|
221
|
+
- 新增回归测试:样式归属标记生效、误删后 2 秒内自动恢复、样式不会重复注入
|
|
222
|
+
|
|
216
223
|
### 0.4.3
|
|
217
224
|
|
|
218
225
|
- **修复折叠侧边栏时入口不收成纯图标(用户反馈)**:收起侧边栏后,shell 把侧栏收成 36×36 图标轨道(layout frame 出现 `data-sidebar-collapsed` 属性、侧栏根节点切换 CSS-Module `*_collapsed` 哈希类),而看板入口仍保持全宽——图标、「任务看板」文字、右侧计数角标挤在窄轨里。修复:折叠信号下入口镜像原生轨道几何(36×36、居中、与原生 newSession 折叠态同款间距),隐藏文字与角标,图标 14→16px 保证可读;双信号选择器(`[data-sidebar-collapsed]` 与 `[class*="_collapsed"]`)沿用 0.4.2 双选择器原则,新旧 shell 通吃;展开态完全不受影响,`aria-label` 保留无障碍提示
|
package/lib/client.js
CHANGED
|
@@ -1586,15 +1586,46 @@ window.__ModuleLoader__.load({
|
|
|
1586
1586
|
.dsh-atb-imp-result { font-size: 12px; color: var(--dsw-alias-state-success-primary, #30a46c); margin-top: 10px; }
|
|
1587
1587
|
.dsh-atb-badge[data-kind="checklist"] { color: var(--dsw-alias-label-secondary, inherit); }
|
|
1588
1588
|
`;
|
|
1589
|
-
|
|
1590
|
-
|
|
1589
|
+
/** Style element id (stable since 0.1.x: hook for tests and debugging). */
|
|
1590
|
+
const STYLE_ID = "dsh-taskboard-styles";
|
|
1591
|
+
/**
|
|
1592
|
+
* Ownership tag for the shell's client-module bookkeeping. The web shell
|
|
1593
|
+
* claims every UNTAGGED `<style>` for whichever plugin module materializes
|
|
1594
|
+
* next (claimStyles in dsh-client-modules), and the client HMR driver
|
|
1595
|
+
* deletes `<style>` tags by this attribute on every rebuilt entry
|
|
1596
|
+
* (removeOwnedStyles in dsh-client-hmr).
|
|
1597
|
+
*/
|
|
1598
|
+
const PLUGIN_ID = "dsh-taskboard";
|
|
1599
|
+
/** Per-stylesheet identity, mirroring the shell's own data-plugin-css. */
|
|
1600
|
+
const CSS_TAG = "dsh-taskboard/styles";
|
|
1601
|
+
/**
|
|
1602
|
+
* Ensure the stylesheet lives in <head>: create when absent, re-attach when
|
|
1603
|
+
* removed, always carry the ownership tags.
|
|
1604
|
+
*
|
|
1605
|
+
* 0.4.4 fix (field report: CSS randomly dropped, board renders as unstyled
|
|
1606
|
+
* HTML until refresh): injection runs from cordis apply(), which resolves
|
|
1607
|
+
* AFTER this module's materialization, so the old untagged <style> could be
|
|
1608
|
+
* claimed by ANY sibling plugin module that materialized later (observed
|
|
1609
|
+
* with lazily-materializing profile bundles). That sibling's next HMR
|
|
1610
|
+
* rebuild then deleted OUR stylesheet, and the old module-level `injected`
|
|
1611
|
+
* flag blocked re-injection until a full page refresh. Pre-tagging pins
|
|
1612
|
+
* ownership to this plugin: sibling claims skip tagged styles, and only
|
|
1613
|
+
* THIS plugin's rebuild removes it — the fresh apply re-injects. Idempotency
|
|
1614
|
+
* is DOM-based for the same reason: a module flag cannot see removals,
|
|
1615
|
+
* getElementById can. A found element is re-tagged too, so a leftover
|
|
1616
|
+
* pre-0.4.4 element adopted across a hot swap heals its ownership.
|
|
1617
|
+
*/
|
|
1591
1618
|
function injectStyles() {
|
|
1592
|
-
if (
|
|
1593
|
-
|
|
1594
|
-
style
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1619
|
+
if (typeof document === "undefined") return;
|
|
1620
|
+
let style = document.getElementById(STYLE_ID);
|
|
1621
|
+
if (style === null) {
|
|
1622
|
+
style = document.createElement("style");
|
|
1623
|
+
style.id = STYLE_ID;
|
|
1624
|
+
style.textContent = STYLES;
|
|
1625
|
+
document.head.append(style);
|
|
1626
|
+
}
|
|
1627
|
+
style.dataset.plugin = PLUGIN_ID;
|
|
1628
|
+
style.dataset.pluginCss = CSS_TAG;
|
|
1598
1629
|
}
|
|
1599
1630
|
|
|
1600
1631
|
//#endregion
|
|
@@ -1834,7 +1865,7 @@ window.__ModuleLoader__.load({
|
|
|
1834
1865
|
* @module dsh-taskboard/shared/version
|
|
1835
1866
|
*/
|
|
1836
1867
|
/** The package version (must equal package.json "version"). */
|
|
1837
|
-
const PLUGIN_VERSION = "0.4.
|
|
1868
|
+
const PLUGIN_VERSION = "0.4.4";
|
|
1838
1869
|
|
|
1839
1870
|
//#endregion
|
|
1840
1871
|
//#region src/client/board/TaskCard.tsx
|
|
@@ -4700,6 +4731,9 @@ window.__ModuleLoader__.load({
|
|
|
4700
4731
|
function apply(ctx) {
|
|
4701
4732
|
try {
|
|
4702
4733
|
injectStyles();
|
|
4734
|
+
const styleWatch = setInterval(() => {
|
|
4735
|
+
injectStyles();
|
|
4736
|
+
}, 2e3);
|
|
4703
4737
|
const controller = new BoardController(createClient());
|
|
4704
4738
|
const connection = ctx.get?.("connection");
|
|
4705
4739
|
if (connection !== void 0) {
|
|
@@ -4743,6 +4777,7 @@ window.__ModuleLoader__.load({
|
|
|
4743
4777
|
console.error("[dsh-taskboard] mount failed:", error);
|
|
4744
4778
|
}
|
|
4745
4779
|
ctx.effect?.(() => () => {
|
|
4780
|
+
clearInterval(styleWatch);
|
|
4746
4781
|
for (const d of disposers.splice(0)) d();
|
|
4747
4782
|
controller.dispose();
|
|
4748
4783
|
}, "dsh-taskboard: client mount");
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-taskboard",
|
|
3
3
|
"description": "Agent-first task board for the DSH web GUI: host-authoritative task ledger with taskboard_* agent tools, project (= workspace) claim boundaries, per-task model execution in fresh sessions, optional per-task git-worktree isolation (dedicated task branches, commit evidence, one-click merge), host-side cron scheduling, and a live SSE kanban view. Mounts via the official dsh plugin system — no DSH source changes.",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.4",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"exports": {
|
package/src/client/index.ts
CHANGED
|
@@ -49,6 +49,11 @@ interface ClientContextFace {
|
|
|
49
49
|
export function apply(ctx: ClientContextFace): void {
|
|
50
50
|
try {
|
|
51
51
|
injectStyles()
|
|
52
|
+
// Stylesheet watchdog (0.4.4): re-assert the stylesheet if anything
|
|
53
|
+
// removed it mid-session — defense-in-depth on top of the ownership
|
|
54
|
+
// tag (see styles.ts for the claim/reload mechanism it guards against).
|
|
55
|
+
// One getElementById per 2s tick; cleared with the plugin teardown.
|
|
56
|
+
const styleWatch = setInterval(() => { injectStyles() }, 2_000)
|
|
52
57
|
const client = createClient()
|
|
53
58
|
const controller = new BoardController(client)
|
|
54
59
|
|
|
@@ -104,7 +109,12 @@ export function apply(ctx: ClientContextFace): void {
|
|
|
104
109
|
// cordis effect semantics: the callback runs immediately and its RETURN
|
|
105
110
|
// VALUE is the disposer (family-plugin precedent: () => () => {...}).
|
|
106
111
|
// A single-layer arrow here executes the teardown immediately.
|
|
112
|
+
// The stylesheet itself is NOT removed here: the HMR driver owns removal
|
|
113
|
+
// of tagged styles on this plugin's rebuild (and a self-removal could
|
|
114
|
+
// race a same-lifetime re-apply); its rules are dsh-atb-* scoped, so a
|
|
115
|
+
// leftover tag after a full disable is inert.
|
|
107
116
|
ctx.effect?.(() => () => {
|
|
117
|
+
clearInterval(styleWatch)
|
|
108
118
|
for (const d of disposers.splice(0)) d()
|
|
109
119
|
controller.dispose()
|
|
110
120
|
}, 'dsh-taskboard: client mount')
|
package/src/client/styles.ts
CHANGED
|
@@ -691,14 +691,47 @@ html[data-dsh-atb-active] .dsh-atb-view { display: flex; flex-direction: column;
|
|
|
691
691
|
.dsh-atb-badge[data-kind="checklist"] { color: var(--dsw-alias-label-secondary, inherit); }
|
|
692
692
|
`
|
|
693
693
|
|
|
694
|
-
|
|
694
|
+
/** Style element id (stable since 0.1.x: hook for tests and debugging). */
|
|
695
|
+
const STYLE_ID = 'dsh-taskboard-styles'
|
|
695
696
|
|
|
696
|
-
/**
|
|
697
|
+
/**
|
|
698
|
+
* Ownership tag for the shell's client-module bookkeeping. The web shell
|
|
699
|
+
* claims every UNTAGGED `<style>` for whichever plugin module materializes
|
|
700
|
+
* next (claimStyles in dsh-client-modules), and the client HMR driver
|
|
701
|
+
* deletes `<style>` tags by this attribute on every rebuilt entry
|
|
702
|
+
* (removeOwnedStyles in dsh-client-hmr).
|
|
703
|
+
*/
|
|
704
|
+
const PLUGIN_ID = 'dsh-taskboard'
|
|
705
|
+
|
|
706
|
+
/** Per-stylesheet identity, mirroring the shell's own data-plugin-css. */
|
|
707
|
+
const CSS_TAG = 'dsh-taskboard/styles'
|
|
708
|
+
|
|
709
|
+
/**
|
|
710
|
+
* Ensure the stylesheet lives in <head>: create when absent, re-attach when
|
|
711
|
+
* removed, always carry the ownership tags.
|
|
712
|
+
*
|
|
713
|
+
* 0.4.4 fix (field report: CSS randomly dropped, board renders as unstyled
|
|
714
|
+
* HTML until refresh): injection runs from cordis apply(), which resolves
|
|
715
|
+
* AFTER this module's materialization, so the old untagged <style> could be
|
|
716
|
+
* claimed by ANY sibling plugin module that materialized later (observed
|
|
717
|
+
* with lazily-materializing profile bundles). That sibling's next HMR
|
|
718
|
+
* rebuild then deleted OUR stylesheet, and the old module-level `injected`
|
|
719
|
+
* flag blocked re-injection until a full page refresh. Pre-tagging pins
|
|
720
|
+
* ownership to this plugin: sibling claims skip tagged styles, and only
|
|
721
|
+
* THIS plugin's rebuild removes it — the fresh apply re-injects. Idempotency
|
|
722
|
+
* is DOM-based for the same reason: a module flag cannot see removals,
|
|
723
|
+
* getElementById can. A found element is re-tagged too, so a leftover
|
|
724
|
+
* pre-0.4.4 element adopted across a hot swap heals its ownership.
|
|
725
|
+
*/
|
|
697
726
|
export function injectStyles(): void {
|
|
698
|
-
if (
|
|
699
|
-
|
|
700
|
-
style
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
727
|
+
if (typeof document === 'undefined') return
|
|
728
|
+
let style = document.getElementById(STYLE_ID)
|
|
729
|
+
if (style === null) {
|
|
730
|
+
style = document.createElement('style')
|
|
731
|
+
style.id = STYLE_ID
|
|
732
|
+
style.textContent = STYLES
|
|
733
|
+
document.head.append(style)
|
|
734
|
+
}
|
|
735
|
+
style.dataset.plugin = PLUGIN_ID
|
|
736
|
+
style.dataset.pluginCss = CSS_TAG
|
|
704
737
|
}
|
package/src/shared/version.ts
CHANGED