✨ 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:
1 parent
61c4728dce
commit
7f460d1257
18 files changed
+847
-240
No files matched your search
@@ -1,47 +1,19 @@
|
||||
import type { Uri } from 'vscode'
|
||||
import type { GitRepository } from '../../git/gitApi'
|
||||
import type { KanbanWebviewPanel } from '../KanbanPanel'
|
||||
import { accessSync, constants } from 'node:fs'
|
||||
import * as path from 'node:path'
|
||||
import { extensions, workspace } from 'vscode'
|
||||
import { workspace } from 'vscode'
|
||||
import { resolveCommitProfileForRun } from '../../cc/commitProfile'
|
||||
import { resolveProfilePath } from '../../cc/profiles'
|
||||
import { spawnClaude } from '../../cc/spawnClaude'
|
||||
import { findEnvFiles, lockEnvFiles, unlockEnvFiles } from '../../files/envLock'
|
||||
import { loadGitApi } from '../../git/gitExtension'
|
||||
import { missingGitIdentityKeys, readGitIdentity } from '../../git/identity'
|
||||
import { logger } from '../../logging/logger'
|
||||
import { getEffectiveCommitProfilePath } from '../../settings/store'
|
||||
import { makeNonce } from '../../webview/html'
|
||||
import { dismiss, toast } from './handoffFlow'
|
||||
|
||||
/**
|
||||
* Minimal structural typing for the bits of the built-in `vscode.git`
|
||||
* extension API we consume to observe working-tree state.
|
||||
* Reference: microsoft/vscode → extensions/git/src/api/git.d.ts
|
||||
*/
|
||||
interface GitExtensionApiRepositoryStateChange {
|
||||
(listener: () => unknown): { dispose: () => void }
|
||||
}
|
||||
|
||||
interface GitExtensionApiRepositoryState {
|
||||
readonly workingTreeChanges: ReadonlyArray<{ uri: Uri }>
|
||||
readonly indexChanges: ReadonlyArray<{ uri: Uri }>
|
||||
readonly untrackedChanges?: ReadonlyArray<{ uri: Uri }>
|
||||
readonly onDidChange: GitExtensionApiRepositoryStateChange
|
||||
}
|
||||
|
||||
interface GitExtensionApiRepository {
|
||||
readonly rootUri: Uri
|
||||
readonly state: GitExtensionApiRepositoryState
|
||||
}
|
||||
|
||||
interface GitExtensionApi {
|
||||
readonly repositories: ReadonlyArray<GitExtensionApiRepository>
|
||||
}
|
||||
|
||||
interface GitExtensionExports {
|
||||
getAPI: (version: 1) => GitExtensionApi
|
||||
}
|
||||
|
||||
export async function handleCommitRun(panel: KanbanWebviewPanel): Promise<void> {
|
||||
if (panel.commitRunning)
|
||||
return
|
||||
@@ -266,26 +238,20 @@ export function setupGitWatcher(panel: KanbanWebviewPanel): void {
|
||||
if (!wsRoot)
|
||||
return
|
||||
|
||||
const gitExt = extensions.getExtension<GitExtensionExports>('vscode.git')
|
||||
if (!gitExt) {
|
||||
logger.add({
|
||||
level: 'warn',
|
||||
source: 'panel',
|
||||
message: 'vscode.git 扩展未找到,提交按钮将持续显示',
|
||||
})
|
||||
// Fallback: keep the button visible so users can at least trigger
|
||||
// commits manually even though we can't observe state.
|
||||
updateHasChanges(panel, true)
|
||||
return
|
||||
}
|
||||
void loadGitApi().then((api) => {
|
||||
if (!api) {
|
||||
logger.add({
|
||||
level: 'warn',
|
||||
source: 'panel',
|
||||
message: 'vscode.git 扩展没装或被禁用,提交按钮将持续显示',
|
||||
})
|
||||
// Fallback: keep the button visible so users can at least trigger
|
||||
// commits manually even though we can't observe state.
|
||||
updateHasChanges(panel, true)
|
||||
return
|
||||
}
|
||||
|
||||
const activation = gitExt.isActive
|
||||
? Promise.resolve(gitExt.exports)
|
||||
: Promise.resolve(gitExt.activate())
|
||||
|
||||
void activation.then((exports) => {
|
||||
const api = exports.getAPI(1)
|
||||
const findRepo = (): GitExtensionApiRepository | undefined =>
|
||||
const findRepo = (): GitRepository | undefined =>
|
||||
api.repositories.find(r => r.rootUri.fsPath === wsRoot)
|
||||
|
||||
const updateState = (): void => {
|
||||
@@ -297,11 +263,11 @@ export function setupGitWatcher(panel: KanbanWebviewPanel): void {
|
||||
const total
|
||||
= repo.state.workingTreeChanges.length
|
||||
+ repo.state.indexChanges.length
|
||||
+ (repo.state.untrackedChanges?.length ?? 0)
|
||||
+ repo.state.untrackedChanges.length
|
||||
updateHasChanges(panel, total > 0)
|
||||
}
|
||||
|
||||
const subscribe = (repo: GitExtensionApiRepository): void => {
|
||||
const subscribe = (repo: GitRepository): void => {
|
||||
panel.gitStateDisposable = repo.state.onDidChange(updateState)
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user