dsh-better-workspace 0.27.2 → 0.28.0

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-better-workspace",
3
- "version": "0.27.2",
3
+ "version": "0.28.0",
4
4
  "main": "./src/index.js",
5
5
  "description": "侧边栏工作区树:按官方磁盘目录嵌套(官方 workspace-tree 语义),可选按名称中的 / 分组(默认关闭,设置里开启);新会话页的工作区选择器同树。Workspace tree for the DSH sidebar workspace list, nested by official disk folders with optional \"/\"-name grouping; the New Session workspace picker shows the same tree.",
6
6
  "engines": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-better-workspace",
3
- "version": "0.27.2",
3
+ "version": "0.28.0",
4
4
  "description": "侧边栏工作区树:按官方磁盘目录嵌套(官方 workspace-tree 语义),可选按名称中的 / 分组(默认关闭,设置里开启);新会话页的工作区选择器同树(同一份视图选项即时同步);添加工作区走官方目录流。Workspace tree for the DSH sidebar: disk-path nesting (official workspace-tree semantics), with optional \"/\"-name grouping (off by default), and the same tree in the New Session workspace picker; add-workspace rides the official directory flow.",
5
5
  "type": "module",
6
6
  "repository": {
package/src/client.js CHANGED
@@ -4553,14 +4553,20 @@ window.__ModuleLoader__.load({
4553
4553
  // v0.16.0: the sidebar no longer draws its own in-app browser. The browse
4554
4554
  // backend SHIPS one (dsh-client-ui-directory-picker-browse, mounted as a
4555
4555
  // host+surface pair, its client half registering into both directory-flow
4556
- // holes) — but it can only be rendered by the entry that DECLARED the
4557
- // child hole (the shipped WorkspaceBrowser), and a child declaration is
4558
- // exclusive, so shadowing that seat forfeits the authorization for good
4559
- // (ui-renderer: "not declared by this entry's children"). A native Host
4560
- // still gets the official OS chooser; a browse Host is pointed at the
4561
- // official in-app flow in the conversation empty state instead of a
4562
- // second-hand imitation. The probe stays: it decides which of the two
4563
- // this page gets, and a refused pick still classifies the backend.
4556
+ // holes) — but it can only be RENDER-AUTHORIZED by the entry that
4557
+ // DECLARED the child hole (the shipped WorkspaceBrowser), and a child
4558
+ // declaration is exclusive, so shadowing that seat forfeits that
4559
+ // authorization for good (ui-renderer: "not declared by this entry's
4560
+ // children").
4561
+ // v0.28.0: that gap no longer punts browse hosts to the empty-state page.
4562
+ // The shipped occupant registers into BOTH holes (the sidebar hole
4563
+ // included), so the sidebar reads its component off the slot ledger —
4564
+ // the v0.22.0 hero read, third use of the shipped-occupant pattern — and
4565
+ // renders it with its own owner conversation. A native Host still gets
4566
+ // the official OS chooser; a ledger that hides the entry keeps the
4567
+ // add-guide pointer as the floor. The probe stays: it decides which of
4568
+ // the two this page gets, and a refused pick still classifies the
4569
+ // backend.
4564
4570
  const pickerState = { kind: 'unknown', probe: null, api: null }
4565
4571
  /**
4566
4572
  * True for the refusal a Host serving the OTHER capability throws: the wire
@@ -6412,6 +6418,7 @@ window.__ModuleLoader__.load({
6412
6418
  insertWorkspaceBefore, insertSessionBefore,
6413
6419
  useDirectoryFlow,
6414
6420
  pickDirectory, listDirectory, createDirectory,
6421
+ sidebarFlowEntry,
6415
6422
  shippedBrowserFace, scheduleSeatReader,
6416
6423
  officialT,
6417
6424
  t,
@@ -8409,20 +8416,47 @@ window.__ModuleLoader__.load({
8409
8416
  onClose: () => setDialog(null),
8410
8417
  t,
8411
8418
  })
8412
- if (dialog.kind === 'add-guide') return E(ui.Modal, {
8413
- key: 'add-guide',
8414
- open: true,
8415
- onClose: () => setDialog(null),
8416
- closeLabel: t('close'),
8417
- title: t('add.guide.title'),
8418
- footer: E('div', { className: 'bw-modal-actions' },
8419
- E(BTN, { variant: 'primary', onClick: () => setDialog(null) }, t('confirm')),
8420
- ),
8421
- },
8422
- E('div', { className: 'bw-modal-body' },
8423
- E('div', { className: 'bw-hint' }, t('add.guide')),
8424
- ),
8425
- )
8419
+ if (dialog.kind === 'add-guide' || dialog.kind === 'add-flow') {
8420
+ // v0.28.0: a browse host gets the SHIPPED in-app dialog right here.
8421
+ // The occupant's component is read off the sidebar hole's ledger
8422
+ // (the hero read, v0.22.0) and rendered with this seat's owner
8423
+ // conversation: a confirmed directory is adopted exactly like a
8424
+ // native pick, dismissal just closes. The ledger hiding the entry
8425
+ // (or an 'add-guide' outright) keeps the pointer dialog as the
8426
+ // floor. All references below are callback-scoped: adoptDirectory
8427
+ // and fail are defined after this IIFE, so no render-time TDZ.
8428
+ const flowEntry = dialog.kind === 'add-flow'
8429
+ && typeof sidebarFlowEntry === 'function' ? sidebarFlowEntry() : null
8430
+ if (flowEntry && flowEntry.component) {
8431
+ let flowFace = null
8432
+ if (typeof flowEntry.inject === 'function') {
8433
+ try { flowFace = flowEntry.inject() } catch (error) { flowFace = null }
8434
+ }
8435
+ return E(flowEntry.component, {
8436
+ key: 'bw-sidebar-flow',
8437
+ open: true,
8438
+ busy: flowBusy,
8439
+ onPicked: (path) => { setDialog(null); if (path) adoptDirectory(String(path)) },
8440
+ onCancel: () => { setDialog(null) },
8441
+ onError: (message) => { setDialog(null); fail(String(message)) },
8442
+ ...(flowFace || EMPTY_FOLDERS),
8443
+ })
8444
+ }
8445
+ return E(ui.Modal, {
8446
+ key: 'add-guide',
8447
+ open: true,
8448
+ onClose: () => setDialog(null),
8449
+ closeLabel: t('close'),
8450
+ title: t('add.guide.title'),
8451
+ footer: E('div', { className: 'bw-modal-actions' },
8452
+ E(BTN, { variant: 'primary', onClick: () => setDialog(null) }, t('confirm')),
8453
+ ),
8454
+ },
8455
+ E('div', { className: 'bw-modal-body' },
8456
+ E('div', { className: 'bw-hint' }, t('add.guide')),
8457
+ ),
8458
+ )
8459
+ }
8426
8460
  return null
8427
8461
  })()
8428
8462
 
@@ -8445,9 +8479,12 @@ window.__ModuleLoader__.load({
8445
8479
  }
8446
8480
 
8447
8481
  // v0.16.0: the sidebar add affordance rides the OFFICIAL chooser only.
8448
- // A `browse` host refuses that pick by design, so the click explains where
8449
- // the official in-app flow lives instead of opening a plugin-built copy —
8450
- // the shipped dialog cannot be rendered from here (see the capability block).
8482
+ // A `browse` host refuses that pick by design — the click used to
8483
+ // explain where the official in-app flow lives instead. v0.28.0: the
8484
+ // browse host now gets that flow RIGHT HERE: 'add-flow' opens the
8485
+ // dialog that reads the shipped occupant off the sidebar hole's ledger
8486
+ // (see the dialog rendering above; the renderSlot authorization stays
8487
+ // with the shipped entry, but the component is on the ledger).
8451
8488
  //
8452
8489
  // The shipped shortcut channel also reports this interaction
8453
8490
  // (setDirectoryBusy): a second Cmd/Ctrl+O while the chooser is open is
@@ -8458,12 +8495,12 @@ window.__ModuleLoader__.load({
8458
8495
  const settle = () => { if (typeof reportDirectoryBusy === 'function') reportDirectoryBusy(false) }
8459
8496
  Promise.resolve(pickerCapabilityNow())
8460
8497
  .then((kind) => {
8461
- if (kind === 'browse') { setDialog({ kind: 'add-guide' }); return undefined }
8498
+ if (kind === 'browse') { setDialog({ kind: 'add-flow' }); return undefined }
8462
8499
  return Promise.resolve()
8463
8500
  .then(() => pickDirectory())
8464
8501
  .then((path) => (path ? adoptDirectory(String(path)) : undefined))
8465
8502
  .catch((reason) => {
8466
- if (pickerRefusal(reason)) { setDialog({ kind: 'add-guide' }); return }
8503
+ if (pickerRefusal(reason)) { setDialog({ kind: 'add-flow' }); return }
8467
8504
  fail(messageOf(reason))
8468
8505
  })
8469
8506
  })
@@ -8781,6 +8818,21 @@ window.__ModuleLoader__.load({
8781
8818
  // Host composes the browse backend instead of the OS chooser.
8782
8819
  listDirectory: (path, signal) => uiWorkspace.listDirectory(path, signal),
8783
8820
  createDirectory: (path, name) => uiWorkspace.createDirectory(path, name),
8821
+ // v0.28.0: the shipped occupant's ledger entry for the SIDEBAR flow
8822
+ // hole (same read as the hero one, v0.22.0). The browse surface
8823
+ // registers into both holes, so its in-app dialog renders from the
8824
+ // sidebar too; a native entry read this way is renderless and would
8825
+ // only re-run the OS chooser the native branch already drives
8826
+ // directly, so the browse probe keeps choosing the path.
8827
+ sidebarFlowEntry: () => {
8828
+ try {
8829
+ const list = slots.entries('sidebar.workspaces.directoryFlow')
8830
+ const entry = Array.isArray(list) && list.length > 0 ? list[0] : null
8831
+ return entry && entry.component ? entry : null
8832
+ } catch (error) {
8833
+ return null
8834
+ }
8835
+ },
8784
8836
  hooks: {
8785
8837
  directoryFlow: flowSource(slots, 'sidebar.workspaces.directoryFlow'),
8786
8838
  },
@@ -8799,14 +8851,16 @@ window.__ModuleLoader__.load({
8799
8851
  }
8800
8852
  }
8801
8853
 
8802
- // The SIDEBAR hole is occupied by our own picking flow at priority -1:
8803
- // rendering the official occupant is impossible here (a child-hole
8804
- // declaration is exclusive — the shipped browser entry keeps owning
8805
- // 'sidebar.workspaces.directoryFlow' even after losing the render race,
8806
- // and re-declaring throws), so the flow probes the backend itself — the
8807
- // OS chooser through the same official host service on native Hosts,
8808
- // the polished in-app dialog on browse Hosts. The HERO hole stays
8809
- // untouched: the conversation empty-state flow is purely official.
8854
+ // The SIDEBAR hole's directory flow is NOT occupied by this plugin
8855
+ // (v0.16.0): a child-hole declaration is exclusive — the shipped
8856
+ // browser entry keeps owning 'sidebar.workspaces.directoryFlow' even
8857
+ // after losing the render race, and re-declaring throws — so the add
8858
+ // flow probes the backend itself: the OS chooser through the same
8859
+ // official host service on native Hosts, and since v0.28.0 the SHIPPED
8860
+ // in-app dialog on browse Hosts, read off the hole's ledger and
8861
+ // rendered with this seat's owner conversation (the hero read,
8862
+ // v0.22.0). The HERO hole is likewise never declared here; the
8863
+ // empty-state picker reads its occupant the same way.
8810
8864
 
8811
8865
  // One shared store handle: the browser and the settings page must see the
8812
8866
  // same persisted state (expansion, folder list, prefs, styling).