dsh-ide-git 0.5.0 → 0.5.2

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.5.0",
3
+ "version": "0.5.2",
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.5.0",
3
+ "version": "0.5.2",
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
@@ -3314,7 +3314,11 @@ window.__ModuleLoader__.load({
3314
3314
  return Object.prototype.hasOwnProperty.call(bag, key)
3315
3315
  }
3316
3316
 
3317
- function dictionaryOf(ctx) {
3317
+ /* The active locale tag, read fresh every time: DSH's language preference
3318
+ switches live (the host-backed preference wins over the browser), so a
3319
+ value captured once at activation would keep answering in the language
3320
+ that happened to be active when the plugin loaded. */
3321
+ function activeLocaleOf(ctx) {
3318
3322
  let active = ''
3319
3323
  try {
3320
3324
  const locale = ctx.get('locale')
@@ -3324,7 +3328,26 @@ window.__ModuleLoader__.load({
3324
3328
  }
3325
3329
  } catch (error) { void error }
3326
3330
  if (active === '' && typeof navigator === 'object' && navigator !== null && typeof navigator.language === 'string') active = navigator.language
3327
- return dictionaryFor(active)
3331
+ return active
3332
+ }
3333
+
3334
+ function dictionaryOf(ctx) {
3335
+ return dictionaryFor(activeLocaleOf(ctx))
3336
+ }
3337
+
3338
+ /* A live lookup: the dictionary is picked per call and cached under the tag
3339
+ it was picked for, so a language switch costs one string compare per
3340
+ string. Falling back to EN — which is kept key-complete on purpose —
3341
+ means an unsupported language shows English, never a raw key. */
3342
+ function translatorOf(ctx) {
3343
+ let cachedTag = null
3344
+ let cachedDict = null
3345
+ return (key) => {
3346
+ const tag = activeLocaleOf(ctx)
3347
+ if (tag !== cachedTag) { cachedTag = tag; cachedDict = dictionaryFor(tag) }
3348
+ if (hasOwnKey(cachedDict, key)) return cachedDict[key]
3349
+ return hasOwnKey(EN, key) ? EN[key] : key
3350
+ }
3328
3351
  }
3329
3352
 
3330
3353
  function fill(template, values) {
@@ -5480,6 +5503,24 @@ window.__ModuleLoader__.load({
5480
5503
  `{ scope, t }`. A session's working directory is the path of the
5481
5504
  workspace that accounts for it — the same value the better-sidebar seat
5482
5505
  delivers as `scope.cwd`. */
5506
+ /* DSH's locale service notifies on every snapshot change, and its own
5507
+ components re-render on that. The panel is not one of DSH's components,
5508
+ so it subscribes for itself: a language switch then repaints the panel
5509
+ instead of waiting for the next page load. Everything the panel draws is
5510
+ inside this wrapper — the better-sidebar tab and the native seat both go
5511
+ through it. */
5512
+ function LocaleLive(props) {
5513
+ const [tick, setTick] = useState(0)
5514
+ useEffect(() => {
5515
+ const locale = props.ctx === undefined ? undefined : props.ctx.get('locale')
5516
+ if (locale === undefined || typeof locale.subscribe !== 'function') return undefined
5517
+ const unsubscribe = locale.subscribe(() => { setTick((value) => value + 1) })
5518
+ return typeof unsubscribe === 'function' ? unsubscribe : undefined
5519
+ }, [])
5520
+ void tick
5521
+ return E(Panel, { scope: props.scope, t: props.t, visible: props.visible })
5522
+ }
5523
+
5483
5524
  function NativePanel(props) {
5484
5525
  const workspaces = typeof props.useWorkspaces === 'function'
5485
5526
  ? props.useWorkspaces(NATIVE_WORKSPACE_ITEMS)
@@ -5495,7 +5536,7 @@ window.__ModuleLoader__.load({
5495
5536
  }
5496
5537
  }
5497
5538
  const scope = useMemo(() => ({ cwd: cwd, sessionId: sessionId }), [cwd, sessionId])
5498
- return E(Panel, { scope: scope, t: props.t, visible: true })
5539
+ return E(LocaleLive, { ctx: props.ctx, scope: scope, t: props.t, visible: true })
5499
5540
  }
5500
5541
 
5501
5542
  function apply(ctx) {
@@ -5505,8 +5546,7 @@ window.__ModuleLoader__.load({
5505
5546
  document.head.appendChild(style)
5506
5547
  ctx.effect(() => () => { style.remove() }, 'dsh-ide-git: panel styles')
5507
5548
 
5508
- const dict = dictionaryOf(ctx)
5509
- const t = (key) => (Object.prototype.hasOwnProperty.call(dict, key) ? dict[key] : key)
5549
+ const t = translatorOf(ctx)
5510
5550
 
5511
5551
  /* DSH's own locale registry: bind this plugin's namespace so host-side
5512
5552
  consumers read exactly the copy the panel does. Every shipped
@@ -5551,7 +5591,7 @@ window.__ModuleLoader__.load({
5551
5591
  })
5552
5592
  const offBody = slots.inject('sidebar.right.pane.tab', () => slots.register(
5553
5593
  { name: 'sidebar.right.pane.tab', key: NATIVE_ID },
5554
- (tabProps) => E(NativePanel, Object.assign({}, tabProps, { t: t })),
5594
+ (tabProps) => E(NativePanel, Object.assign({}, tabProps, { t: t, ctx: ctx })),
5555
5595
  ))
5556
5596
  disposeNative = () => {
5557
5597
  try { offBody() } catch (error) { void error }
@@ -5564,15 +5604,33 @@ window.__ModuleLoader__.load({
5564
5604
  if (betterSidebar === undefined || typeof betterSidebar.registerTab !== 'function') return
5565
5605
  hostedByBetterSidebar = true
5566
5606
  if (disposeNative !== null) { disposeNative(); disposeNative = null }
5567
- tabCtx.effect(() => betterSidebar.registerTab({
5568
- id: TAB_ID,
5569
- title: () => t('title'),
5570
- description: () => t('description'),
5571
- icon: (size) => E(Icon, { name: 'commit', size: size === undefined ? 16 : size }),
5572
- order: 21,
5573
- single: true,
5574
- component: (tabProps) => E(Panel, Object.assign({}, tabProps, { t: t })),
5575
- }), 'dsh-ide-git: Git tab')
5607
+ tabCtx.effect(() => {
5608
+ const offTab = betterSidebar.registerTab({
5609
+ id: TAB_ID,
5610
+ title: () => t('title'),
5611
+ description: () => t('description'),
5612
+ icon: (size) => E(Icon, { name: 'commit', size: size === undefined ? 16 : size }),
5613
+ order: 21,
5614
+ single: true,
5615
+ component: (tabProps) => E(LocaleLive, {
5616
+ ctx: ctx,
5617
+ scope: tabProps.scope,
5618
+ t: t,
5619
+ visible: tabProps.visible,
5620
+ }),
5621
+ })
5622
+ /* The base can go away at RUNTIME (disabled in the plugin panel, or
5623
+ uninstalled): cordis unloads this effect when the service
5624
+ disappears, and the panel must fall back to the native
5625
+ right-sidebar seats instead of vanishing with the base. The
5626
+ same inject re-fires when the service returns, and the
5627
+ callback above takes the native seats down again. */
5628
+ return () => {
5629
+ try { offTab() } catch (error) { void error }
5630
+ hostedByBetterSidebar = false
5631
+ hostNatively()
5632
+ }
5633
+ }, 'dsh-ide-git: Git tab')
5576
5634
  })
5577
5635
 
5578
5636
  /* ctx.inject runs its callback straight away when the service is already