dsh-better-workspace 0.13.0 → 0.14.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 +1 -1
- package/package.json +1 -1
- package/src/client.js +56 -19
package/dsh.plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-external/dsh-better-workspace",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"main": "./src/index.js",
|
|
5
5
|
"description": "侧边栏工作区两层层级树:工作区按磁盘目录嵌套(官方 workspace-tree 语义),名称中的 / 即虚拟分组(web/前端 · web/后端);添加工作区由官方目录流承载。Two-layer hierarchy tree for the DSH sidebar workspace list.",
|
|
6
6
|
"engines": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-better-workspace",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "侧边栏工作区两层层级树:磁盘目录嵌套(官方 workspace-tree 语义)+ 名称 / 虚拟分组,添加工作区走官方目录流。Two-layer workspace tree for the DSH sidebar: disk-path nesting plus \"/\"-name groups; add-workspace rides the official directory flow.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
package/src/client.js
CHANGED
|
@@ -4726,6 +4726,7 @@ window.__ModuleLoader__.load({
|
|
|
4726
4726
|
insertWorkspaceBefore, insertSessionBefore,
|
|
4727
4727
|
useDirectoryFlow,
|
|
4728
4728
|
pickDirectory, listDirectory, createDirectory,
|
|
4729
|
+
officialT,
|
|
4729
4730
|
t,
|
|
4730
4731
|
} = props
|
|
4731
4732
|
|
|
@@ -5659,30 +5660,42 @@ window.__ModuleLoader__.load({
|
|
|
5659
5660
|
|
|
5660
5661
|
/* ------------------------- context menu ------------------------ */
|
|
5661
5662
|
|
|
5662
|
-
|
|
5663
|
+
// Context-menu entries mirror the OFFICIAL row menus item-for-item
|
|
5664
|
+
// (ui-workspace Rows.tsx workspaceMenuItems / sessionMenuItems): same
|
|
5665
|
+
// ids, same icons, same danger semantics, and — through the official
|
|
5666
|
+
// 'workspace' dictionary — the same copy, so upstream rewording lands
|
|
5667
|
+
// here without a plugin release. What the official menus cannot
|
|
5668
|
+
// provide is the bw-only surface: name-group / session-group rename
|
|
5669
|
+
// and Customize appearance, appended after a separator.
|
|
5670
|
+
const ot = typeof officialT === 'function' ? officialT : null
|
|
5671
|
+
const menuEntries = () => {
|
|
5663
5672
|
if (ctx === null) return []
|
|
5673
|
+
const customizeEntry = { id: 'customize', label: t('custom.title'), icon: icon('IconPersonalizationOutline16', 16) }
|
|
5664
5674
|
if (ctx.kind === 'folder') return [
|
|
5665
|
-
{ id: 'rename-folder', label: t('menu.renameFolder') },
|
|
5666
|
-
{
|
|
5667
|
-
|
|
5675
|
+
{ id: 'rename-folder', label: t('menu.renameFolder'), icon: icon('IconEditOutline16', 16) },
|
|
5676
|
+
{ type: 'separator', id: 'bw-sep' },
|
|
5677
|
+
customizeEntry,
|
|
5668
5678
|
]
|
|
5669
5679
|
if (ctx.kind === 'workspace') return [
|
|
5670
|
-
{ id: 'rename', label: t('menu.rename') },
|
|
5671
|
-
{ id: 'delete', label: t('menu.delete'), danger: true },
|
|
5672
|
-
{
|
|
5673
|
-
|
|
5680
|
+
{ id: 'rename', label: ot ? ot('rename') : t('menu.rename'), icon: icon('IconEditOutline16', 16) },
|
|
5681
|
+
{ id: 'delete', label: ot ? ot('delete.workspace') : t('menu.delete'), icon: icon('IconTrashOutline16', 16), danger: true },
|
|
5682
|
+
{ type: 'separator', id: 'bw-sep' },
|
|
5683
|
+
customizeEntry,
|
|
5674
5684
|
]
|
|
5675
5685
|
if (ctx.kind === 'session') return [
|
|
5676
|
-
{ id: 'rename', label: t('menu.rename') },
|
|
5677
|
-
{ id: 'fork', label: t('menu.fork') },
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5686
|
+
{ id: 'rename', label: ot ? ot('rename') : t('menu.rename'), icon: icon('IconEditOutline16', 16) },
|
|
5687
|
+
{ id: 'fork', label: ot ? ot('menu.fork') : t('menu.fork'), icon: icon('IconBranchOutline16', 16) },
|
|
5688
|
+
// Official semantics (Rows.tsx): archive hides the row through the
|
|
5689
|
+
// registry-global archive set and never touches the session log —
|
|
5690
|
+
// deliberately NOT styled destructive.
|
|
5691
|
+
{ id: 'archive', label: ot ? ot('menu.archiveSession') : t('menu.archive'), icon: icon('IconArchiveOutline20', 16) },
|
|
5692
|
+
{ type: 'separator', id: 'bw-sep' },
|
|
5693
|
+
customizeEntry,
|
|
5681
5694
|
]
|
|
5682
5695
|
return [
|
|
5683
|
-
{ id: 'rename-sgroup', label: t('menu.renameSgroup') },
|
|
5684
|
-
{
|
|
5685
|
-
|
|
5696
|
+
{ id: 'rename-sgroup', label: t('menu.renameSgroup'), icon: icon('IconEditOutline16', 16) },
|
|
5697
|
+
{ type: 'separator', id: 'bw-sep' },
|
|
5698
|
+
customizeEntry,
|
|
5686
5699
|
]
|
|
5687
5700
|
}
|
|
5688
5701
|
const handleCtxPick = (id) => {
|
|
@@ -5835,7 +5848,20 @@ window.__ModuleLoader__.load({
|
|
|
5835
5848
|
t,
|
|
5836
5849
|
}),
|
|
5837
5850
|
dialogElement,
|
|
5838
|
-
ctx !== null ? E(
|
|
5851
|
+
(ctx !== null && typeof ui.Menu === 'function') ? E(ui.Menu, {
|
|
5852
|
+
// Right-click opens the SAME menu surface the official ⋯ button
|
|
5853
|
+
// renders (primitives Menu, portal, dense): getAnchorRect feeds
|
|
5854
|
+
// the event coordinates as the anchor rect — portal mode positions
|
|
5855
|
+
// from it directly, no in-place wrapper needed.
|
|
5856
|
+
open: true,
|
|
5857
|
+
onClose: () => setCtx(null),
|
|
5858
|
+
items: menuEntries(),
|
|
5859
|
+
onSelect: handleCtxPick,
|
|
5860
|
+
align: 'start',
|
|
5861
|
+
dense: true,
|
|
5862
|
+
portal: true,
|
|
5863
|
+
getAnchorRect: () => new DOMRect(ctx.x, ctx.y, 0, 0),
|
|
5864
|
+
}) : (ctx !== null ? E('div', {
|
|
5839
5865
|
className: 'bw-ctx-overlay',
|
|
5840
5866
|
onMouseDown: () => setCtx(null),
|
|
5841
5867
|
onContextMenu: (e) => e.preventDefault(),
|
|
@@ -5846,7 +5872,7 @@ window.__ModuleLoader__.load({
|
|
|
5846
5872
|
onMouseDown: (e) => e.stopPropagation(),
|
|
5847
5873
|
onContextMenu: (e) => e.preventDefault(),
|
|
5848
5874
|
},
|
|
5849
|
-
|
|
5875
|
+
menuEntries().map((item, index) => item.type === 'separator'
|
|
5850
5876
|
? E('div', { key: 'sep-' + index, className: 'bw-ctx-sep' })
|
|
5851
5877
|
: E('button', {
|
|
5852
5878
|
key: item.id,
|
|
@@ -5856,7 +5882,7 @@ window.__ModuleLoader__.load({
|
|
|
5856
5882
|
}, item.label),
|
|
5857
5883
|
),
|
|
5858
5884
|
),
|
|
5859
|
-
) : null,
|
|
5885
|
+
) : null),
|
|
5860
5886
|
E(CustomizeDialog, {
|
|
5861
5887
|
open: customize !== null,
|
|
5862
5888
|
kind: customize ? customize.kind : undefined,
|
|
@@ -5919,6 +5945,14 @@ window.__ModuleLoader__.load({
|
|
|
5919
5945
|
// the handle before any flow can open.
|
|
5920
5946
|
pickerState.api = uiWorkspace
|
|
5921
5947
|
|
|
5948
|
+
// The OFFICIAL browser's own dictionary (NS 'workspace'), bound so the
|
|
5949
|
+
// context menu COPY follows upstream wording automatically — the menu
|
|
5950
|
+
// mirrors the official row menus item-for-item (Rows.tsx), and this
|
|
5951
|
+
// way upstream rewording lands here without a plugin release. Falls
|
|
5952
|
+
// back to this plugin's aligned dictionary when bind fails.
|
|
5953
|
+
let officialT = null
|
|
5954
|
+
try { officialT = ctx.locale.bind('workspace') } catch { officialT = null }
|
|
5955
|
+
|
|
5922
5956
|
if (ctx.locale && typeof ctx.locale.register === 'function') {
|
|
5923
5957
|
ctx.effect(() => {
|
|
5924
5958
|
try {
|
|
@@ -5955,6 +5989,9 @@ window.__ModuleLoader__.load({
|
|
|
5955
5989
|
}
|
|
5956
5990
|
|
|
5957
5991
|
const browserInjected = () => ({
|
|
5992
|
+
// Official 'workspace' dictionary translate (menu copy follows upstream);
|
|
5993
|
+
// null when the bind failed — the menu then uses the aligned bw copy.
|
|
5994
|
+
officialT,
|
|
5958
5995
|
startSession: (workspaceId) => { uiWorkspace.startSession(workspaceId) },
|
|
5959
5996
|
open: (sessionId) => { uiWorkspace.openSession(sessionId) },
|
|
5960
5997
|
searchSessions,
|