feat: Redesign git changes to split stage/unstaged files. (#1359)

* feat: Redesign git changes to split stage/unstaged files.

Signed-off-by: Paolo Insogna <paolo@cowtech.it>

* fixup

Signed-off-by: Paolo Insogna <paolo@cowtech.it>

* fixup

Signed-off-by: Paolo Insogna <paolo@cowtech.it>

* refactor: streamline git changes panel

* fix: label staged and working diff tabs

* fix: isolate staged and working diff files

* fix: scope staged and working diff updates

* fix: scope git row revert to working changes

---------

Signed-off-by: Paolo Insogna <paolo@cowtech.it>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
This commit is contained in:
Paolo Insogna
2026-05-24 00:49:38 +03:00
committed by GitHub
co-authored by Bohdan Triapitsyn
parent 9af0de0056
commit e16097b05d
42 changed files with 2987 additions and 923 deletions
+53 -2
View File
@@ -200,7 +200,11 @@ export async function getGitFileDiff(directory: string, options: GetGitFileDiffO
return response.json();
}
export async function revertGitFile(directory: string, filePath: string): Promise<void> {
export async function revertGitFile(
directory: string,
filePath: string,
options?: { scope?: 'all' | 'working' }
): Promise<void> {
if (!filePath) {
throw new Error('path is required to revert git changes');
}
@@ -208,7 +212,7 @@ export async function revertGitFile(directory: string, filePath: string): Promis
const response = await fetch(buildUrl(`${API_BASE}/revert`, directory), {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ path: filePath }),
body: JSON.stringify({ path: filePath, scope: options?.scope }),
});
if (!response.ok) {
@@ -219,6 +223,52 @@ export async function revertGitFile(directory: string, filePath: string): Promis
}
}
export async function stageGitFile(directory: string, filePath: string): Promise<void> {
await stageGitFiles(directory, [filePath]);
}
export async function stageGitFiles(directory: string, filePaths: string[]): Promise<void> {
const paths = filePaths.map((path) => path.trim()).filter(Boolean);
if (paths.length === 0) {
throw new Error('path is required to stage git changes');
}
const response = await fetch(buildUrl(`${API_BASE}/stage`, directory), {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ paths }),
});
if (!response.ok) {
const message = await response.json().catch(() => ({ error: response.statusText }));
throw new Error(message.error || 'Failed to stage git changes');
}
}
export async function unstageGitFile(directory: string, filePath: string): Promise<void> {
await unstageGitFiles(directory, [filePath]);
}
export async function unstageGitFiles(directory: string, filePaths: string[]): Promise<void> {
const paths = filePaths.map((path) => path.trim()).filter(Boolean);
if (paths.length === 0) {
throw new Error('path is required to unstage git changes');
}
const response = await fetch(buildUrl(`${API_BASE}/unstage`, directory), {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ paths }),
});
if (!response.ok) {
const message = await response.json().catch(() => ({ error: response.statusText }));
throw new Error(message.error || 'Failed to unstage git changes');
}
}
export async function isLinkedWorktree(directory: string): Promise<boolean> {
if (!directory) {
return false;
@@ -494,6 +544,7 @@ export async function createGitCommit(
message,
addAll: options.addAll ?? false,
files: options.files,
stageFiles: options.stageFiles,
}),
});
if (!response.ok) {