dsh-code-ui 1.1.3 → 1.1.4

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/lib/client.js CHANGED
@@ -1087,22 +1087,44 @@ window.__ModuleLoader__.load({
1087
1087
  )
1088
1088
  }
1089
1089
 
1090
- /* ============ §8 装配与 slot 注册 ============ */
1091
- slots.inject('conversation.session.header.actions', () => slots.register(
1092
- { name: 'conversation.session.header.actions', id: 'cdex-input-bridge', order: 9999, label: '' },
1093
- (props) => h(InputBridge, props),
1094
- ))
1095
- slots.inject('shell.overlay', () => {
1096
- const d1 = slots.register(
1097
- { name: 'shell.overlay', id: 'cdex-mode-tabs', order: 5, label: '界面模式' },
1098
- () => h(ModeTabs, null),
1099
- )
1100
- const d2 = slots.register(
1101
- { name: 'shell.overlay', id: 'cdex-workbench', order: 10, label: '代码编辑器' },
1102
- () => h(Workbench, null),
1103
- )
1104
- return () => { if (d1) d1(); if (d2) d2() }
1105
- })
1090
+ /* ============ §8 装配与 slot 注册(受「启用开关」控制,可动态挂/卸载) ============ */
1091
+ // 开关存 host 端 settings(enabled 字段,持久化)。默认启用:
1092
+ // get-self 失败 / 字段缺失(旧 host)时绝不隐藏编辑器,只有明确 enabled===false 才不挂载。
1093
+ let unmountEditorFns = null
1094
+ function mountEditor() {
1095
+ if (unmountEditorFns) return
1096
+ const disposers = []
1097
+ disposers.push(slots.inject('conversation.session.header.actions', () => slots.register(
1098
+ { name: 'conversation.session.header.actions', id: 'cdex-input-bridge', order: 9999, label: '' },
1099
+ (props) => h(InputBridge, props),
1100
+ )))
1101
+ disposers.push(slots.inject('shell.overlay', () => {
1102
+ const d1 = slots.register(
1103
+ { name: 'shell.overlay', id: 'cdex-mode-tabs', order: 5, label: '界面模式' },
1104
+ () => h(ModeTabs, null),
1105
+ )
1106
+ const d2 = slots.register(
1107
+ { name: 'shell.overlay', id: 'cdex-workbench', order: 10, label: '代码编辑器' },
1108
+ () => h(Workbench, null),
1109
+ )
1110
+ return () => { if (d1) d1(); if (d2) d2() }
1111
+ }))
1112
+ unmountEditorFns = () => { disposers.forEach((d) => { try { d() } catch (e) {} }) }
1113
+ }
1114
+ function unmountEditor() {
1115
+ if (!unmountEditorFns) return
1116
+ try { unmountEditorFns() } catch (e) {}
1117
+ unmountEditorFns = null
1118
+ }
1119
+ // 卡片里切换开关 -> set-enabled 成功后调用:立即挂/卸载编辑器(无需刷新页面、无需重启 DSH)
1120
+ function applyEnabled(v) {
1121
+ if (v) mountEditor()
1122
+ else unmountEditor()
1123
+ }
1124
+ // 启动时先查开关再挂载(RPC 失败 = 默认启用)
1125
+ callHost('get-self').then((r) => {
1126
+ applyEnabled(!(r && !r.error && r.enabled === false))
1127
+ }).catch(() => applyEnabled(true))
1106
1128
 
1107
1129
  /* ---- 插件配置卡片(settings.plugin.item):信息 + 检查更新 / 一键更新 / 本地包更新 ---- */
1108
1130
  function PluginConfigCard() {
@@ -1111,9 +1133,27 @@ window.__ModuleLoader__.load({
1111
1133
  const [chk, setChk] = React.useState(null)
1112
1134
  const [run, setRun] = React.useState(null)
1113
1135
  const [localPath, setLocalPath] = React.useState('')
1136
+ const [enabling, setEnabling] = React.useState(false)
1114
1137
  const lastPayloadRef = React.useRef(null)
1115
1138
  const pollDisposeRef = React.useRef(null)
1116
1139
 
1140
+ // 编辑器开关:写 host settings 持久化;成功后立即挂/卸载编辑器 UI
1141
+ function toggleEnabled() {
1142
+ if (!self || enabling) return
1143
+ const next = self.enabled === false
1144
+ setEnabling(true)
1145
+ callHost('set-enabled', { enabled: next }).then((r) => {
1146
+ setEnabling(false)
1147
+ if (r && !r.error) {
1148
+ setSelf(Object.assign({}, self, { enabled: next }))
1149
+ applyEnabled(next)
1150
+ showToast(next ? '已启用编辑器(立即生效)' : '已禁用编辑器(立即生效)')
1151
+ } else {
1152
+ showToast('切换失败:' + ((r && r.error) || '未知错误'))
1153
+ }
1154
+ })
1155
+ }
1156
+
1117
1157
  function stopPoll() {
1118
1158
  if (pollDisposeRef.current) { try { pollDisposeRef.current() } catch (e) {} pollDisposeRef.current = null }
1119
1159
  }
@@ -1186,6 +1226,19 @@ window.__ModuleLoader__.load({
1186
1226
  : h('span', { className: 'cdx-pc-chevron' + (cardOpen ? ' cdx-pc-chevron-open' : '') }, '▾'),
1187
1227
  ),
1188
1228
  cardOpen ? h('div', { className: 'cdx-pc-body' },
1229
+ // 字段零:编辑器启用开关
1230
+ h('div', { className: 'cdx-pc-field' },
1231
+ h('div', { className: 'cdx-pc-head' },
1232
+ h('span', { className: 'cdx-pc-label' }, '编辑器开关(页面入口 + 编辑器整体)'),
1233
+ h('button', {
1234
+ type: 'button',
1235
+ className: 'cdx-pc-btn ' + (self && self.enabled !== false ? 'cdx-pc-btn-outline' : 'cdx-pc-btn-primary'),
1236
+ disabled: !self || enabling,
1237
+ onClick: toggleEnabled,
1238
+ }, enabling ? '切换中…' : (self && self.enabled !== false ? '已启用 · 点击禁用' : '已禁用 · 点击启用')),
1239
+ ),
1240
+ h('p', { className: 'cdx-pc-note' }, '切换立即生效(实时挂载/卸载编辑器),无需重启 DSH,也无需刷新页面;若个别界面未跟着变化,普通刷新(F5)即可。开关状态持久化保存。'),
1241
+ ),
1189
1242
  // 字段一:在线检查更新
1190
1243
  h('div', { className: 'cdx-pc-field' },
1191
1244
  h('div', { className: 'cdx-pc-head' },
package/lib/index.js CHANGED
@@ -94,16 +94,20 @@ const CODE_UI_SETTINGS_NS = settingsNamespace("dsh-code-ui");
94
94
  const CodeUiSettingsSchema = z.object({
95
95
  // 检查更新用的 registry(只影响在线「检查」;安装仍走 profile 自己的 .npmrc)
96
96
  updateRegistry: z.string().default(REGISTRY_DEFAULT),
97
+ // 编辑器总开关:false 时 client 端不挂载编辑器 UI(配置卡片始终保留,可随时再开)
98
+ enabled: z.boolean().default(true),
97
99
  });
98
100
  // 解析后的当前值:settings 服务未挂载/未写入时保持默认
99
- const selfSettings = { updateRegistry: REGISTRY_DEFAULT };
101
+ const selfSettings = { updateRegistry: REGISTRY_DEFAULT, enabled: true };
102
+ // settings 服务引用(「启用/禁用」开关写入用;由 installSelfSettings 捕获)
103
+ let settingsServiceRef = null;
100
104
  function installSelfSettings(ctx) {
101
- let source = () => ({ updateRegistry: selfSettings.updateRegistry });
105
+ let source = () => ({ updateRegistry: selfSettings.updateRegistry, enabled: selfSettings.enabled });
102
106
  installSettingsSection(
103
107
  ctx,
104
108
  CODE_UI_SETTINGS_NS,
105
109
  CodeUiSettingsSchema,
106
- { updateRegistry: selfSettings.updateRegistry },
110
+ { updateRegistry: selfSettings.updateRegistry, enabled: selfSettings.enabled },
107
111
  {
108
112
  setSource: (current) => { source = current; },
109
113
  onChange: () => {
@@ -112,10 +116,13 @@ function installSelfSettings(ctx) {
112
116
  if (typeof v.updateRegistry === "string" && /^https?:\/\//.test(v.updateRegistry)) {
113
117
  selfSettings.updateRegistry = v.updateRegistry.replace(/\/+$/, "");
114
118
  }
119
+ if (typeof v.enabled === "boolean") selfSettings.enabled = v.enabled;
115
120
  } catch (_) {}
116
121
  },
117
122
  },
118
123
  );
124
+ // 捕获 settings 服务实例:卡片的「启用/禁用」开关经 set-enabled RPC 写入本命名空间
125
+ ctx.inject(["settings"], (sctx) => { settingsServiceRef = sctx.settings; });
119
126
  }
120
127
 
121
128
  async function fetchLatestVersion(name, registry) {
@@ -463,9 +470,25 @@ function rpcHandler(ctx) {
463
470
  profileRoot: profileRoot,
464
471
  workspace: profileRoot ? existsSync(join(profileRoot, "pnpm-workspace.yaml")) : false,
465
472
  updateRegistry: selfSettings.updateRegistry,
473
+ enabled: selfSettings.enabled !== false,
466
474
  });
467
475
  }
468
476
 
477
+ if (endpoint === "set-enabled") {
478
+ if (typeof args.enabled !== "boolean") return ok({ error: "enabled 参数需为布尔值" });
479
+ if (!settingsServiceRef || typeof settingsServiceRef.update !== "function") {
480
+ return ok({ error: "settings 服务不可用,重启 DSH 后再试" });
481
+ }
482
+ try {
483
+ // 写入命名空间(schema 校验 + 持久化;watch 会经 onChange 再同步一次 selfSettings)
484
+ await settingsServiceRef.update(CODE_UI_SETTINGS_NS, { enabled: args.enabled });
485
+ selfSettings.enabled = args.enabled;
486
+ return ok({ ok: true, enabled: args.enabled });
487
+ } catch (err) {
488
+ return ok({ error: "写入设置失败:" + ((err && err.message) || String(err)) });
489
+ }
490
+ }
491
+
469
492
  if (endpoint === "check-update") {
470
493
  const out = { current: SELF_VERSION, latest: null, updateAvailable: false, notPublished: false, registryUsed: null, error: null };
471
494
  // 主源 = 设置里的 updateRegistry(默认官方源,镜像有同步滞后);主源不可达时用另一个兜底做「检查」
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-code-ui",
3
- "version": "1.1.3",
3
+ "version": "1.1.4",
4
4
  "description": "Cursor 风格的 AI 代码编辑器工作台插件(DSH):文件树、多标签页编辑、引用/备注/翻译、内嵌 AI 输入框、语法高亮",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",