✨ feat(vscode): 代码阅读侧栏加「未提交的更改」筛选

- 标题栏新按钮「未提交的更改」:树里只剩工作区各 git 仓库里没提交的文件(暂存、没暂存、未跟踪、合并冲突),每个有改动的仓库一个根,跟着 git 状态自动重摆;上色和徽标交给 VS Code 自带的 git 装饰
- 两种筛选互斥,由 TreeFilters 统一管,上下文键合并成 superpowers.codeReader.filter(review / uncommitted)
- 改动文件树改成多根,buildChangedTree 挪到 explorer/changedTree 并改吃 {path, change}
- 内置 git 扩展 API 的类型和加载抽到 src/git/gitApi、gitExtension,提交按钮的监听也改用它
- 文件注释按文件所在的工作区文件夹记,不看树从哪个根摆下来
This commit is contained in:
cruldra committed 2026-09-29 23:42:10 +08:00
1 parent 61c4728dce
commit 7f460d1257
18 files changed
+847 -240

No files matched your search

+20 -12
View File
@@ -103,35 +103,43 @@ describe('右键菜单的注释', () => {
})
})
describe('审查工单', () => {
const REVIEWING = 'superpowers.codeReader.reviewing'
describe('筛选(审查工单、未提交的更改)', () => {
const FILTER = 'superpowers.codeReader.filter'
const PICK = 'superpowers.codeReader.pickReviewIssue'
const UNCOMMITTED = 'superpowers.codeReader.showUncommitted'
const SHOW_ALL = 'superpowers.codeReader.showAllFiles'
it('标题栏:第一个「选工单」,审查时才有「显示全部」,然后「刷新」', () => {
it('标题栏:选工单、未提交的更改、开着筛选时才有的「显示全部」、刷新', () => {
const title = menus['view/title']
.filter(item => item.when.startsWith('view == superpowers.codeReader.files'))
.sort((a, b) => orderOf(a) - orderOf(b))
expect(title.map(item => item.command)).toEqual([PICK, SHOW_ALL, 'superpowers.codeReader.refresh'])
expect(title.map(item => item.command)).toEqual([PICK, UNCOMMITTED, SHOW_ALL, 'superpowers.codeReader.refresh'])
expect(title.every(item => item.group?.startsWith('navigation'))).toBe(true)
expect(title.find(item => item.command === SHOW_ALL)?.when).toContain(`&& ${REVIEWING}`)
expect(title.find(item => item.command === PICK)?.when).not.toContain(REVIEWING)
expect(title.find(item => item.command === SHOW_ALL)?.when).toBe(`view == superpowers.codeReader.files && ${FILTER}`)
for (const command of [PICK, UNCOMMITTED])
expect(title.find(item => item.command === command)?.when).not.toContain(FILTER)
})
it('按钮的字和图标:选工单 git-pull-request,显示全部 close', () => {
it('按钮的字和图标:选工单 git-pull-request,未提交的更改 git-commit,显示全部 close', () => {
expect(commands.find(item => item.command === PICK)).toMatchObject({ title: '选工单', icon: '$(git-pull-request)' })
expect(commands.find(item => item.command === UNCOMMITTED)).toMatchObject({ title: '未提交的更改', icon: '$(git-commit)' })
expect(commands.find(item => item.command === SHOW_ALL)).toMatchObject({ title: '显示全部', icon: '$(close)' })
})
it('审查时行上没有注释按钮(工作副本里不记注释),复制照旧', () => {
it('审查时行上没有注释按钮(工作副本里不记注释),未提交的更改时照常有;复制照旧', () => {
const noteItems = menus['view/item/context'].filter(item => item.command === ADD_NOTE || item.command === EDIT_NOTE)
expect(noteItems.length).toBeGreaterThan(0)
expect(noteItems.every(item => item.when.includes(`!${REVIEWING}`))).toBe(true)
expect(noteItems.every(item => item.when.includes(`${FILTER} != review`))).toBe(true)
const copyItems = menus['view/item/context'].filter(item => item.submenu === COPY_MENU || item.command?.startsWith('superpowers.codeReader.copy'))
expect(copyItems.some(item => item.when.includes(REVIEWING))).toBe(false)
expect(copyItems.some(item => item.when.includes(FILTER))).toBe(false)
})
it('命令面板里「显示全部」只在审查时有', () => {
expect(menus.commandPalette.find(item => item.command === SHOW_ALL)?.when).toBe(REVIEWING)
it('命令面板里「显示全部」只在开着筛选时有', () => {
expect(menus.commandPalette.find(item => item.command === SHOW_ALL)?.when).toBe(FILTER)
})
it('只用一个上下文键,旧的 superpowers.codeReader.reviewing 不再出现', () => {
const whens = Object.values(menus).flat().map(item => item.when)
expect(whens.some(when => when.includes('superpowers.codeReader.reviewing'))).toBe(false)
})
})