dsh-ide-git 0.19.6 → 0.19.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/dsh.plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "dsh-external/dsh-ide-git",
3
- "version": "0.19.6",
3
+ "version": "0.19.7",
4
4
  "main": "./src/index.js",
5
5
  "description": "IDE 级 Git 操作面板:分支树 + 提交图谱 + 变更/暂存/提交 + 提交详情。装了 dsh-better-sidebar 时挂成它的原生 tab(右侧栏 + 底部工作台);没装时直接挂 DSH 原生右侧栏,单独安装即可用。JetBrains 风格 Git 工具窗口 for DeepSeek Harness.",
6
6
  "engines": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-ide-git",
3
- "version": "0.19.6",
3
+ "version": "0.19.7",
4
4
  "description": "DSH plugin: an IDE-grade Git tool window as a native dsh-better-sidebar tab — branch tree, commit graph, changes, commit details, JetBrains-style actions, in the right sidebar and the bottom panel. | DSH 插件:IDE 级 Git 工具窗口,以 dsh-better-sidebar 原生 Tab 挂载——分支树 / 提交图谱 / 变更与提交详情 / JetBrains 风格操作,右侧栏与底部面板双布局自适应。",
5
5
  "type": "module",
6
6
  "repository": {
package/src/client.js CHANGED
@@ -9751,6 +9751,24 @@ window.__ModuleLoader__.load({
9751
9751
  /* A host that serves the document but refuses writes gets disabled switches
9752
9752
  and a sentence, not controls that silently do nothing. */
9753
9753
  const readOnly = snapshot.writable !== true
9754
+ /* The three placement switches (conversation tab / immersive / composer
9755
+ pill) share one target rule: the control's own answer wins; otherwise
9756
+ the target is the INVERSE of what is on screen — the synchronous intent
9757
+ when the user already touched the field, the accepted document
9758
+ otherwise. The parentheses are load-bearing: `cond ? a : b !== false`
9759
+ parses as `cond ? a : (b !== false)`, so the old spelling of the
9760
+ fallback (`: values[field] !== false) !== true`) made a label click a
9761
+ silent no-op — it recomputed the CURRENT value and wrote it back
9762
+ unchanged (v0.19.6 user report, fixed in v0.19.7). Keep the inversion
9763
+ on the whole expression, never on its last operand. */
9764
+ const placementShown = (field) => (Object.prototype.hasOwnProperty.call(intent.current, field)
9765
+ ? intent.current[field] === true
9766
+ : values[field] !== false)
9767
+ const placementTarget = (field, fromControl) => {
9768
+ if (fromControl !== null) return fromControl
9769
+ const current = placementShown(field)
9770
+ return current !== true
9771
+ }
9754
9772
  return wrapCard(E('div', { className: 'dig-settings dig-card-body', 'data-settings-status': status, 'data-settings-readonly': readOnly === true ? 'true' : 'false' },
9755
9773
  E('div', { className: readOnly === true ? 'dig-settings-note' : 'dig-settings-note dig-settings-note-hidden', 'data-settings-readonly-note': '' }, t('settings.rail.readonly')),
9756
9774
  note === '' ? null : E('div', { className: 'dig-settings-error', 'data-settings-error': '' }, note),
@@ -9815,20 +9833,14 @@ window.__ModuleLoader__.load({
9815
9833
  (() => {
9816
9834
  const field = 'conversationTab'
9817
9835
  const inputId = 'dig-placement-' + field
9818
- const shown = Object.prototype.hasOwnProperty.call(intent.current, field)
9819
- ? intent.current[field] === true
9820
- : values[field] !== false
9836
+ const shown = placementShown(field)
9821
9837
  const toggle = (event) => {
9822
9838
  if (readOnly === true) { setNote(t('settings.rail.readonly')); return }
9823
9839
  const fromControl = event !== undefined && event !== null && event.target !== null
9824
9840
  && event.target !== undefined && typeof event.target.checked === 'boolean'
9825
9841
  ? event.target.checked
9826
9842
  : null
9827
- const wanted = fromControl !== null
9828
- ? fromControl
9829
- : (Object.prototype.hasOwnProperty.call(intent.current, field)
9830
- ? intent.current[field] !== true
9831
- : values[field] !== false) !== true
9843
+ const wanted = placementTarget(field, fromControl)
9832
9844
  intent.current[field] = wanted
9833
9845
  dirty.current.set(field, wanted)
9834
9846
  setPending((now) => Object.assign({}, now, { [field]: wanted }))
@@ -9859,20 +9871,14 @@ window.__ModuleLoader__.load({
9859
9871
  same config). */
9860
9872
  const field = 'immersive'
9861
9873
  const inputId = 'dig-placement-' + field
9862
- const shown = Object.prototype.hasOwnProperty.call(intent.current, field)
9863
- ? intent.current[field] === true
9864
- : values[field] !== false
9874
+ const shown = placementShown(field)
9865
9875
  const toggle = (event) => {
9866
9876
  if (readOnly === true) { setNote(t('settings.rail.readonly')); return }
9867
9877
  const fromControl = event !== undefined && event !== null && event.target !== null
9868
9878
  && event.target !== undefined && typeof event.target.checked === 'boolean'
9869
9879
  ? event.target.checked
9870
9880
  : null
9871
- const wanted = fromControl !== null
9872
- ? fromControl
9873
- : (Object.prototype.hasOwnProperty.call(intent.current, field)
9874
- ? intent.current[field] !== true
9875
- : values[field] !== false) !== true
9881
+ const wanted = placementTarget(field, fromControl)
9876
9882
  intent.current[field] = wanted
9877
9883
  dirty.current.set(field, wanted)
9878
9884
  setPending((now) => Object.assign({}, now, { [field]: wanted }))
@@ -9902,20 +9908,14 @@ window.__ModuleLoader__.load({
9902
9908
  disappears live. Default ON. */
9903
9909
  const field = 'composerStatus'
9904
9910
  const inputId = 'dig-placement-' + field
9905
- const shown = Object.prototype.hasOwnProperty.call(intent.current, field)
9906
- ? intent.current[field] === true
9907
- : values[field] !== false
9911
+ const shown = placementShown(field)
9908
9912
  const toggle = (event) => {
9909
9913
  if (readOnly === true) { setNote(t('settings.rail.readonly')); return }
9910
9914
  const fromControl = event !== undefined && event !== null && event.target !== null
9911
9915
  && event.target !== undefined && typeof event.target.checked === 'boolean'
9912
9916
  ? event.target.checked
9913
9917
  : null
9914
- const wanted = fromControl !== null
9915
- ? fromControl
9916
- : (Object.prototype.hasOwnProperty.call(intent.current, field)
9917
- ? intent.current[field] !== true
9918
- : values[field] !== false) !== true
9918
+ const wanted = placementTarget(field, fromControl)
9919
9919
  intent.current[field] = wanted
9920
9920
  dirty.current.set(field, wanted)
9921
9921
  setPending((now) => Object.assign({}, now, { [field]: wanted }))
@@ -14544,10 +14544,15 @@ window.__ModuleLoader__.load({
14544
14544
  vars, which are absent when that feature is off — the seat inherits
14545
14545
  guaranteed-invalid values, and var() fallbacks do NOT rescue IVCT, so the
14546
14546
  whole background chain below resolves to transparent. Re-declaring the two
14547
- aliases from the official static token (the exact source the light theme's
14548
- own alias defs point at, theme-correct in dark too) makes the chain valid
14549
- again regardless of any-bg's injection state. */
14547
+ aliases from the official static token — the exact source the LIGHT
14548
+ theme's own alias defs point at — makes the chain valid again regardless
14549
+ of any-bg's injection state. static never varies by theme, so this only
14550
+ reproduces the LIGHT surface; the dark override right below re-pins the
14551
+ same aliases to the dark theme's own sources (layer-1→bluish-875,
14552
+ layer-2→bluish-850). Without that override every dark theme renders
14553
+ white surfaces under light text here (issue #15, 1.13:1). */
14550
14554
  '.dig-selection-bar{--dsw-alias-bg-layer-1:var(--dsw-static-neutral-bluish-00,#fff);--dsw-alias-bg-layer-2:var(--dsw-static-neutral-bluish-00,#fff);display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:5px 10px;margin:6px 0;font-size:11px;line-height:16px;border-radius:var(--dsw-radius-sm,8px);background:var(--dsh-any-op-menu-cordis,var(--dsw-alias-bg-layer-2));border:1px solid var(--dsw-alias-border-l2,var(--dsw-alias-border-subtle,transparent));box-shadow:var(--dsw-elevation-prominent,0 4px 14px rgba(0,0,0,.25))}',
14555
+ 'body[data-ds-dark-theme] .dig-selection-bar{--dsw-alias-bg-layer-1:var(--dsw-static-neutral-bluish-875,#232324);--dsw-alias-bg-layer-2:var(--dsw-static-neutral-bluish-850,#2c2c2e)}',
14551
14556
  '.dig-selection-bar .dig-link{margin-left:0;padding:2px 0}',
14552
14557
  '.dig-selection-bar .dig-link-danger{color:var(--dsw-alias-state-error-primary)}',
14553
14558
  '.dig-selection-count{color:var(--dsw-alias-label-secondary);white-space:nowrap}',
@@ -14761,8 +14766,12 @@ window.__ModuleLoader__.load({
14761
14766
  // surface sampling misses and that remap would otherwise IVCT to transparent).
14762
14767
  // --dsh-any-op-menu-cordis at the input opacity tier, plus its input blur rule), so fill
14763
14768
  // opacity and frost follow the composer card exactly. Without that plugin the
14764
- // theme-owned menu material applies.
14769
+ // theme-owned menu material applies. The light re-declaration on the rule below
14770
+ // pins the LIGHT static surface (see the .dig-selection-bar note); dark themes
14771
+ // need the matching override right after it, or the menu renders white under
14772
+ // light text (issue #15).
14765
14773
  '.dig-cs-menu{--dsw-alias-bg-layer-1:var(--dsw-static-neutral-bluish-00,#fff);--dsw-alias-bg-layer-2:var(--dsw-static-neutral-bluish-00,#fff);position:absolute;bottom:calc(100% + 6px);left:0;z-index:60;min-width:220px;max-width:320px;max-height:320px;overflow:auto;padding:6px;border-radius:var(--dsw-radius-lg,12px);background:var(--dsh-any-op-menu-cordis,var(--dsw-alias-bg-layer-2));box-shadow:var(--dsw-elevation-prominent,var(--dsw-elevation-dimmed,0 8px 24px rgba(0,0,0,.2)));color:var(--dsw-alias-label-secondary);font-size:12px;line-height:20px}',
14774
+ 'body[data-ds-dark-theme] .dig-cs-menu{--dsw-alias-bg-layer-1:var(--dsw-static-neutral-bluish-875,#232324);--dsw-alias-bg-layer-2:var(--dsw-static-neutral-bluish-850,#2c2c2e)}',
14766
14775
  '.dig-cs-item{display:flex;align-items:center;gap:8px;width:100%;padding:5px 10px;border:none;border-radius:var(--dsw-radius-sm,8px);background:transparent;color:var(--dsw-alias-label-primary);font-family:inherit;font-size:13px;line-height:20px;cursor:pointer;text-align:left}',
14767
14776
  '.dig-cs-item:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}',
14768
14777
  '.dig-cs-item:disabled{opacity:.5;cursor:default}',
package/src/index.js CHANGED
@@ -77,6 +77,13 @@ function railConfigSchema(schema) {
77
77
  does not mark volatile ("Config field … is not volatile"), and the settings
78
78
  switch then rolls back silently. */
79
79
  shape.immersive = live(schema.boolean().default(true))
80
+ /* Composer status pill (v0.19.0): the settings card's "输入框 Git 状态" switch
81
+ and the pill itself read this field. v0.19.0-v0.19.6 shipped the switch and
82
+ the reader WITHOUT this declaration, so the Host rejected every write with
83
+ `Config field "composerStatus" is not volatile` — the card rolled the switch
84
+ back and said "设置没写进去". Any new row-Config field the client writes MUST
85
+ be declared (and volatile) here, or the write is refused before it lands. */
86
+ shape.composerStatus = live(schema.boolean().default(true))
80
87
  return schema.object(shape)
81
88
  }
82
89