dsh-global-todo 0.4.5 → 0.4.7
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/CHANGELOG.md +21 -0
- package/docs/DESIGN.md +3 -1
- package/docs/screenshots/panel-detail.png +0 -0
- package/docs/screenshots/panel-select.png +0 -0
- package/docs/screenshots/panel.png +0 -0
- package/lib/client.js +65 -9
- package/lib/index.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.4.7] — 2026-10-19
|
|
11
|
+
|
|
12
|
+
Verified against the running GUI this time, with measured numbers instead of arithmetic.
|
|
13
|
+
|
|
14
|
+
- **The card no longer overlaps the list by its own padding.** `width: 360px` was applied
|
|
15
|
+
content-box, so the card was 394px wide while the list reserved 380px — a 14px overlap that
|
|
16
|
+
only showed up in a live box measurement. It is `box-sizing: border-box` now (990–1350 against
|
|
17
|
+
a list ending at 970 at 1440×900).
|
|
18
|
+
- **Its vertical brackets come from the list, not the panel.** The panel fills the window, so
|
|
19
|
+
measuring its bottom put the card over the footer; the anchors now come from `.gt-groups`
|
|
20
|
+
(top + 10) and its bottom (+ 8 gap above the footer).
|
|
21
|
+
## [0.4.6] — 2026-10-19
|
|
22
|
+
|
|
23
|
+
The card existed; where it landed depended on a viewport assumption that the real shell does not
|
|
24
|
+
honour.
|
|
25
|
+
|
|
26
|
+
- **The detail card is measured from the panel, not from `50vw`.** In the GUI the plugin slot does
|
|
27
|
+
not fill the window, so the viewport-derived right edge put the card on top of the list; the card
|
|
28
|
+
now measures `.gt-inner` on open, on window resize and on a slot resize (sidebar collapse), and
|
|
29
|
+
positions itself from that rectangle. The CSS fallback (used by the static previews, which are
|
|
30
|
+
server-rendered and run no effects) assumes the centred 980px column.
|
|
10
31
|
## [0.4.5] — 2026-10-19
|
|
11
32
|
|
|
12
33
|
Polishing where the side detail sits, now that it exists.
|
package/docs/DESIGN.md
CHANGED
|
@@ -63,7 +63,9 @@ Expanding a row inline is right on a narrow window and wrong on a wide one: the
|
|
|
63
63
|
row you were reading slides away, and the rest of the screen sits empty. Above 1100px the open
|
|
64
64
|
row's detail is lifted out of the flow into a card bracketed between the toolbar and the footer
|
|
65
65
|
at the panel's right edge; only the list gives way (the toolbar keeps full width), and the list gets
|
|
66
|
-
padding equal to that card.
|
|
66
|
+
padding equal to that card. The card's offsets are measured from the panel's own column on mount
|
|
67
|
+
and on resize — the slot does not always fill the window, so a viewport-derived offset put the card
|
|
68
|
+
over the list inside the real GUI. This is a CSS-only override over unchanged markup
|
|
67
69
|
(`.gt-root[data-wide-detail]` plus one media query) precisely so there is still exactly one
|
|
68
70
|
detail implementation — a second render path for wide screens would drift from the inline one at
|
|
69
71
|
the first field change.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/lib/client.js
CHANGED
|
@@ -50,7 +50,7 @@ window.__ModuleLoader__.load({
|
|
|
50
50
|
* different mechanisms (restart vs. hot reload), so "which one am I looking
|
|
51
51
|
* at" needs an answer that the bundle itself carries.
|
|
52
52
|
*/
|
|
53
|
-
const UI_REV = '
|
|
53
|
+
const UI_REV = 'ui30'
|
|
54
54
|
/** Last language resolved for the shell; module-level so a fetch failure can be worded too. */
|
|
55
55
|
let activeLang = 'zh'
|
|
56
56
|
|
|
@@ -1014,13 +1014,19 @@ button.gt-chip[data-on="1"] { color: var(--dsw-alias-label-primary); border-colo
|
|
|
1014
1014
|
@media (min-width: 1100px) {
|
|
1015
1015
|
/* Only the list gives way: the title row and the toolbar keep their full width, so the
|
|
1016
1016
|
controls never wrap or hide behind the card. */
|
|
1017
|
-
.gt-root[data-wide-detail="1"] .gt-groups { padding-right:
|
|
1017
|
+
.gt-root[data-wide-detail="1"] .gt-groups { padding-right: 380px; }
|
|
1018
|
+
.gt-root[data-wide-detail="1"] .gt-inner { position: relative; }
|
|
1018
1019
|
.gt-root[data-wide-detail="1"] .gt-item[data-open="1"] .gt-detail {
|
|
1019
|
-
/*
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1020
|
+
/* Anchored to the panel's own column (.gt-inner), not to the viewport: the slot does not
|
|
1021
|
+
always fill the window, and a viewport-centred offset put the card over the list. */
|
|
1022
|
+
/* The var fallback matters for the static previews (server-rendered, so effects never
|
|
1023
|
+
run): they assume the panel is the centred 980px column. */
|
|
1024
|
+
/* border-box matters: 360px is the whole card, so the list's 380px reservation leaves
|
|
1025
|
+
a gap instead of overlapping by the padding width. */
|
|
1026
|
+
box-sizing: border-box;
|
|
1027
|
+
position: fixed; top: var(--gt-detail-top, 208px);
|
|
1028
|
+
right: var(--gt-detail-right, max(24px, calc((100vw - 980px) / 2 + 24px)));
|
|
1029
|
+
bottom: var(--gt-detail-bottom, 64px); width: 360px;
|
|
1024
1030
|
overflow: auto; padding: 16px; margin: 0; border: 1px solid var(--dsw-alias-border-l2);
|
|
1025
1031
|
border-radius: 12px; background: var(--dsw-alias-bg-overlay); z-index: 30;
|
|
1026
1032
|
}
|
|
@@ -2147,6 +2153,10 @@ button.gt-chip[data-on="1"] { color: var(--dsw-alias-label-primary); border-colo
|
|
|
2147
2153
|
// The store counts file changes made outside this process (another machine, a sync
|
|
2148
2154
|
// client). A new count means the panel's view was stale a moment ago; say so once.
|
|
2149
2155
|
const externalRef = useRef(null)
|
|
2156
|
+
// The wide-screen detail card floats over the panel, so its offsets are measured from
|
|
2157
|
+
// the panel's own column rather than derived from the viewport width.
|
|
2158
|
+
const innerRef = useRef(null)
|
|
2159
|
+
const [detailAnchor, setDetailAnchor] = useState(null)
|
|
2150
2160
|
const titleRef = useRef(null)
|
|
2151
2161
|
const searchRef = useRef(null)
|
|
2152
2162
|
const undoTimer = useRef(null)
|
|
@@ -2200,6 +2210,39 @@ button.gt-chip[data-on="1"] { color: var(--dsw-alias-label-primary); border-colo
|
|
|
2200
2210
|
}
|
|
2201
2211
|
}, [lang])
|
|
2202
2212
|
|
|
2213
|
+
useEffect(() => {
|
|
2214
|
+
if (expandedId === '' || typeof window === 'undefined') {
|
|
2215
|
+
setDetailAnchor(null)
|
|
2216
|
+
return undefined
|
|
2217
|
+
}
|
|
2218
|
+
const measure = () => {
|
|
2219
|
+
const element = innerRef.current
|
|
2220
|
+
if (element === null) return
|
|
2221
|
+
const rect = element.getBoundingClientRect()
|
|
2222
|
+
// Bracket the card against the scrolling list, not the panel box: the footer sits
|
|
2223
|
+
// below the list, and the panel's own bottom is below that.
|
|
2224
|
+
const groups = document.querySelector('.gt-groups')
|
|
2225
|
+
const list = groups === null ? null : groups.getBoundingClientRect()
|
|
2226
|
+
setDetailAnchor({
|
|
2227
|
+
top: Math.round((list === null ? rect.top + 190 : list.top) + 10),
|
|
2228
|
+
right: Math.round(window.innerWidth - rect.right + 20),
|
|
2229
|
+
bottom: Math.round(window.innerHeight - (list === null ? rect.bottom : list.bottom) + 8),
|
|
2230
|
+
})
|
|
2231
|
+
}
|
|
2232
|
+
measure()
|
|
2233
|
+
window.addEventListener('resize', measure)
|
|
2234
|
+
// The slot can change width without a window resize (sidebar collapse), which would
|
|
2235
|
+
// leave the card at stale coordinates.
|
|
2236
|
+
// `window.` on purpose: the static scan rejects a bare global it cannot see defined.
|
|
2237
|
+
const Observer = typeof window.ResizeObserver === 'function' ? window.ResizeObserver : null
|
|
2238
|
+
const observer = Observer === null ? null : new Observer(measure)
|
|
2239
|
+
if (observer !== null && innerRef.current !== null) observer.observe(innerRef.current)
|
|
2240
|
+
return () => {
|
|
2241
|
+
window.removeEventListener('resize', measure)
|
|
2242
|
+
if (observer !== null) observer.disconnect()
|
|
2243
|
+
}
|
|
2244
|
+
}, [expandedId, lang])
|
|
2245
|
+
|
|
2203
2246
|
useEffect(() => {
|
|
2204
2247
|
mounted.current = true
|
|
2205
2248
|
void reload()
|
|
@@ -2777,10 +2820,23 @@ button.gt-chip[data-on="1"] { color: var(--dsw-alias-label-primary); border-colo
|
|
|
2777
2820
|
|
|
2778
2821
|
return h(
|
|
2779
2822
|
'div',
|
|
2780
|
-
{
|
|
2823
|
+
{
|
|
2824
|
+
className: 'gt-root',
|
|
2825
|
+
'data-wide-detail': expandedId === '' ? '0' : '1',
|
|
2826
|
+
// The slot does not always fill the window, so the card's viewport offsets are
|
|
2827
|
+
// measured from the panel itself instead of assumed from 50vw.
|
|
2828
|
+
style:
|
|
2829
|
+
detailAnchor === null
|
|
2830
|
+
? undefined
|
|
2831
|
+
: {
|
|
2832
|
+
'--gt-detail-top': `${detailAnchor.top}px`,
|
|
2833
|
+
'--gt-detail-right': `${detailAnchor.right}px`,
|
|
2834
|
+
'--gt-detail-bottom': `${detailAnchor.bottom}px`,
|
|
2835
|
+
},
|
|
2836
|
+
},
|
|
2781
2837
|
h(
|
|
2782
2838
|
'div',
|
|
2783
|
-
{ className: 'gt-inner' },
|
|
2839
|
+
{ className: 'gt-inner', ref: innerRef },
|
|
2784
2840
|
h(
|
|
2785
2841
|
'div',
|
|
2786
2842
|
{ className: 'gt-head' },
|
package/lib/index.js
CHANGED
|
@@ -35,7 +35,7 @@ import { createStore, resolveStorePath } from './store.js'
|
|
|
35
35
|
import { createTools } from './tools.js'
|
|
36
36
|
|
|
37
37
|
/** Must equal `package.json`'s version; `npm run check` enforces that. */
|
|
38
|
-
export const VERSION = '0.4.
|
|
38
|
+
export const VERSION = '0.4.7'
|
|
39
39
|
|
|
40
40
|
/** Plugin id. Also the Loader row id in `cordis.patch.yml`. */
|
|
41
41
|
export const name = 'dsh-global-todo'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-global-todo",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.7",
|
|
4
4
|
"icon": "./docs/icon.svg",
|
|
5
5
|
"description": "Global, cross-session todos for DeepSeek Harness: one list owned by the human and the agent together, with creation time, attached documents and links, and one-click hand-off to an agent session. 全局待办:跨会话一份清单,记录加入时间,可挂文档与地址,可一键交给 Agent 继续干。",
|
|
6
6
|
"type": "module",
|