dsh-vscode-mode 0.1.26 → 0.1.28
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 +62 -30
- package/lib/client.js.map +1 -1
- package/package.json +1 -1
- package/src/client/compat.ts +6 -3
- package/src/client/index.ts +52 -20
package/package.json
CHANGED
package/src/client/compat.ts
CHANGED
|
@@ -54,17 +54,20 @@ export interface SlotSpec {
|
|
|
54
54
|
* @param ctx 客户端上下文(slots 服务)
|
|
55
55
|
* @param spec slot 描述
|
|
56
56
|
* @param render 渲染函数
|
|
57
|
+
* @returns 注销函数(未注册返回 null;形态切换时用于卸载旧 slot)
|
|
57
58
|
*/
|
|
58
|
-
export function registerSlotSafely(ctx: { slots?: { inject?: (name: string, register: () => unknown) => unknown; register?: (...args: unknown[]) => unknown } }, spec: SlotSpec, render: (props: unknown) => unknown): void {
|
|
59
|
+
export function registerSlotSafely(ctx: { slots?: { inject?: (name: string, register: () => unknown) => unknown; register?: (...args: unknown[]) => unknown } }, spec: SlotSpec, render: (props: unknown) => unknown): (() => void) | null {
|
|
59
60
|
const slots = ctx?.slots as { inject: (name: string, register: () => unknown) => unknown; register: (...args: unknown[]) => unknown } | undefined
|
|
60
61
|
if (!slots || typeof slots.inject !== 'function' || typeof slots.register !== 'function') {
|
|
61
62
|
console.warn('[' + PLUGIN_NAME + '] slots 服务不可用,跳过 slot ' + spec.name)
|
|
62
|
-
return
|
|
63
|
+
return null
|
|
63
64
|
}
|
|
64
65
|
try {
|
|
65
|
-
slots.inject(spec.name, () => slots.register(spec, render))
|
|
66
|
+
const disposer = slots.inject(spec.name, () => slots.register(spec, render))
|
|
67
|
+
return typeof disposer === 'function' ? disposer as () => void : null
|
|
66
68
|
} catch (error) {
|
|
67
69
|
console.warn('[' + PLUGIN_NAME + '] slot ' + spec.name + ' 注册失败(' + String(error) + '),已跳过')
|
|
70
|
+
return null
|
|
68
71
|
}
|
|
69
72
|
}
|
|
70
73
|
|
package/src/client/index.ts
CHANGED
|
@@ -37,7 +37,10 @@ import { createOutlinePanel } from './outline/index.js'
|
|
|
37
37
|
import { createOutlineSourceRegistry, registerBuiltinOutlineSources } from './outline/sources.js'
|
|
38
38
|
import type { CompatAdapter } from '../shared/compat.js'
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
// ⚠️ inject 只列必需服务:webUiSettings 是 @linxin666/dsh-client-ui-web-ui-settings 提供的
|
|
41
|
+
// 可选兼容桥(非官方服务),列入 inject 会让未装该桥的部署启动时 entry 永久 pending,
|
|
42
|
+
// web boot 直接失败('1 entry did not activate')。兼容层用 ctx.get 运行时探测 + 降级,不靠 inject。
|
|
43
|
+
export const inject = ['slots', 'timer', 'locale', 'connection', 'remote', 'workspaces', 'sessions', 'conversation', 'settingsScope']
|
|
41
44
|
|
|
42
45
|
/**
|
|
43
46
|
* 装配客户端:注册中央编辑区视图与 header 差异角标。
|
|
@@ -76,7 +79,7 @@ export function apply(ctx: any): void {
|
|
|
76
79
|
const settings = binder.scope
|
|
77
80
|
let selected = autoValue('auto')
|
|
78
81
|
/** 可选探测 betterSidebar 服务(不进 inject:缺失会让插件停靠等待,杀死回退路径)。 */
|
|
79
|
-
|
|
82
|
+
let sideService = detectSidebarService(ctx)
|
|
80
83
|
/** 「添加到对话」动作集:编辑区/Tab 右键菜单注入文件引用与代码块(conversation 服务缺失时各动作安全降级)。 */
|
|
81
84
|
const addToConversation = createAddToConversation(ctx)
|
|
82
85
|
|
|
@@ -142,8 +145,8 @@ export function apply(ctx: any): void {
|
|
|
142
145
|
|
|
143
146
|
// 中央「文件编辑」页签(旧形态回退):类 VSCode 编辑器;侧边栏形态可用时编辑器住 betterSidebar Tab,
|
|
144
147
|
// 本页签不注册(避免双实例:Monaco×2 + diff dock 每会话单源抢占)。
|
|
145
|
-
const registerLegacyTab = (): void => {
|
|
146
|
-
registerSlotSafely(ctx, {
|
|
148
|
+
const registerLegacyTab = (): (() => void) | null => {
|
|
149
|
+
return registerSlotSafely(ctx, {
|
|
147
150
|
name: 'conversation.view',
|
|
148
151
|
id: 'edrv-editor',
|
|
149
152
|
order: 5,
|
|
@@ -152,23 +155,52 @@ export function apply(ctx: any): void {
|
|
|
152
155
|
}, (props: unknown) => React.createElement(EditorView, Object.assign({}, props, { layout: 'tab', sideHint: SIDEBAR_INSTALL_CMD, schedule, addToConversation, sidebarPanels, outlineSources, fileMenuItems })))
|
|
153
156
|
}
|
|
154
157
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
158
|
+
// 侧边栏/中央页签两形态互斥切换:sideDisposer(侧边栏 Tab)与 legacyDisposer(中央页签)只保留其一。
|
|
159
|
+
// ⚠️ betterSidebar 服务由 dsh-better-sidebar 的 client bundle(1MB+)在页面加载时提供,本插件
|
|
160
|
+
// bundle 较小往往先执行完启动检测——一次性探测会误报「未检测到」并永久停在中央页签形态(实测
|
|
161
|
+
// 竞态:better-sidebar 已装,但「文件编辑」Tab 未注册)。故启动后按 2s 间隔重试(窗口 ~30s),
|
|
162
|
+
// 命中即自动切换侧边栏形态;始终未命中则保持中央页签回退。
|
|
163
|
+
let sideDisposer: (() => void) | null = null
|
|
164
|
+
let legacyDisposer: (() => void) | null = null
|
|
165
|
+
const applySideForm = (): void => {
|
|
166
|
+
if (sideService) {
|
|
167
|
+
if (sideDisposer !== null) return
|
|
168
|
+
if (legacyDisposer !== null) { legacyDisposer(); legacyDisposer = null }
|
|
169
|
+
sideDisposer = ctx.effect(() => installSideEditor({
|
|
170
|
+
service: sideService as NonNullable<typeof sideService>,
|
|
171
|
+
renderTab: (props: Record<string, unknown>) => React.createElement(SideEditorTab, Object.assign({}, props, { schedule, addToConversation, sidebarPanels, outlineSources, fileMenuItems })),
|
|
172
|
+
activeSession: () => {
|
|
173
|
+
const snapshot = sessions?.list?.getSnapshot?.() as { current?: string; byId?: Record<string, { cwd?: string }> } | undefined
|
|
174
|
+
const sessionId = snapshot?.current
|
|
175
|
+
if (!sessionId) return undefined
|
|
176
|
+
return { sessionId, cwd: snapshot?.byId?.[sessionId]?.cwd }
|
|
177
|
+
},
|
|
178
|
+
registerLegacyFallback: registerLegacyTab,
|
|
179
|
+
}), 'vscode-mode: sidebar editor tab')
|
|
180
|
+
} else {
|
|
181
|
+
if (legacyDisposer !== null) return
|
|
182
|
+
if (sideDisposer !== null) { sideDisposer(); sideDisposer = null }
|
|
183
|
+
setEnsureSideEditor(null)
|
|
184
|
+
legacyDisposer = registerLegacyTab()
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
applySideForm()
|
|
188
|
+
let sideRetries = 0
|
|
189
|
+
const retrySideService = (): void => {
|
|
190
|
+
if (sideService !== undefined || sideRetries >= 15) return
|
|
191
|
+
sideRetries += 1
|
|
192
|
+
schedule(() => {
|
|
193
|
+
if (sideService !== undefined) return
|
|
194
|
+
sideService = detectSidebarService(ctx)
|
|
195
|
+
if (sideService !== undefined) {
|
|
196
|
+
console.info('[dsh-vscode-mode] 检测到 ' + SIDEBAR_PLUGIN + ',切换侧边栏编辑形态')
|
|
197
|
+
applySideForm()
|
|
198
|
+
} else {
|
|
199
|
+
retrySideService()
|
|
200
|
+
}
|
|
201
|
+
}, 2000)
|
|
171
202
|
}
|
|
203
|
+
retrySideService()
|
|
172
204
|
|
|
173
205
|
// 对话输入框上方差异 dock:普通对话显示单文案按钮,文件编辑页由 EditorView 隐藏
|
|
174
206
|
registerSlotSafely(ctx, {
|