feat: 服务化改造 — ctx.betterSidebar 注册表(registerTab/registerFileViewer),内置 6 tab + 6 viewer 迁移到 registry,v0.4.0
- 新增 src/client/service.ts: BetterSidebarService 接口 + createBetterSidebarService 工厂
- registerTab/registerFileViewer 返回 disposer(HMR-safe,挂到 cordis fiber)
- matchFileViewer 三段匹配: priority desc → detect(内容嗅探) → exts
- openTab 走 descriptor.dedupeKey 统一去重(替代 isSingle/editor-path/diff-id 三分支)
- createTab 回调支持自定义 tab 创建(terminal 的 nextTerminal 递增)
- 新增 src/client/builtins.tsx: 6 内置 tab + 6 内置 viewer 自我注册(吃狗粮)
- tab: editor(hidden) / explorer / git / subagent / terminal / diff(hidden)
- viewer: image / pdf / docx / xlsx / pptx / binary-download
- code/markdown 保持 EditorView 内联兜底(matchFileViewer 返回 undefined 时走 fsRead+CodeMirror)
- 新增 src/client/OrphanedTab.tsx: 未注册 type 的占位组件(插件未加载时降级)
- 改造 src/client/index.tsx: ctx.provide('betterSidebar') + registerBuiltins
- 改造 src/client/Sidebar.tsx: TabContent/buildNewTabOptions/onNewTab 查表替代 switch
- 改造 src/client/EditorView.tsx: 预览路由查 matchFileViewer 替代 if/else 链
- 改造 src/client/state.ts: TabType 联合字面量→string,sanitizeNode 接受所有 string type
- 改造 src/context-types.ts: declare module 'cordis' 加 betterSidebar 字段
- 改造 src/index.ts: re-export Context + 服务类型(consumer import type 触发 augmentation)
- package.json: 加 ./client/service exports 子路径,version 0.4.0
- tests/service.spec.ts: 12 个新测试覆盖 register/dispose/matchFileViewer/dedupe/createTab
- tests/unit.spec.ts: sanitizeState 测试更新(未知 type 不再被拒绝,渲染 OrphanedTab)
This commit is contained in:
+16
-8
@@ -11,7 +11,18 @@
|
||||
*/
|
||||
import { SIDEBAR_PREFS_DEFAULTS, type SidebarPrefs } from '../prefs-shared.ts'
|
||||
|
||||
export type TabType = 'explorer' | 'git' | 'editor' | 'terminal' | 'subagent' | 'diff'
|
||||
/**
|
||||
* Tab type identifier. Builtins use the strings below; external plugins
|
||||
* register their own ids (e.g. `'my-plugin:db'`) through the sidebar
|
||||
* service. Kept as `string` so the registry is open; {@link SIDEBAR_BUILTIN_TAB_TYPES}
|
||||
* lists the builtins for back-compat checks.
|
||||
*/
|
||||
export type TabType = string
|
||||
|
||||
/** The tab type ids the plugin itself registers (see {@link ./builtins.ts}). */
|
||||
export const SIDEBAR_BUILTIN_TAB_TYPES = [
|
||||
'explorer', 'git', 'editor', 'terminal', 'subagent', 'diff',
|
||||
] as readonly string[]
|
||||
|
||||
/** What a diff tab shows: a worktree/index change of one path, or one commit's full patch. */
|
||||
export type SidebarDiffRef =
|
||||
@@ -622,13 +633,10 @@ function sanitizeNode(node: unknown, seen: Set<string>, reid: Map<string, string
|
||||
droppedDiff = true
|
||||
continue
|
||||
}
|
||||
if (
|
||||
candidate.type !== 'explorer' && candidate.type !== 'git'
|
||||
&& candidate.type !== 'editor' && candidate.type !== 'terminal'
|
||||
&& candidate.type !== 'subagent'
|
||||
) {
|
||||
return undefined
|
||||
}
|
||||
// Tab types are an open set (external plugins register their own);
|
||||
// accept any string type here — an unregistered type renders an
|
||||
// <OrphanedTab/> at view time and recovers if its plugin loads later.
|
||||
if (typeof candidate.type !== 'string') return undefined
|
||||
tabs.push({
|
||||
id: candidate.id,
|
||||
type: candidate.type,
|
||||
|
||||
Reference in New Issue
Block a user