mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-08 17:02:17 +00:00
feat(vcs): offer Compare With… in the editor and tab menus, and outside the desktop app (#433)
Compare With… was only in the Project view menu and needed the OS file dialog. The editor context menu (with Compare with Clipboard) and the editor tab menu now offer it too, and outside the desktop app (remote development, browser) a browser file picker supplies the file, compared as text. Co-authored-by: a-rookie-of-C-language <[email protected]>
This commit is contained in:
1 parent
9295a8f78a
commit
19b96b60a4
4 files changed
+101
-3
No files matched your search
@@ -708,6 +708,12 @@ export class EditorController implements SlotHost {
|
||||
localHistoryMenu(slot.model.path),
|
||||
gitMenu(slot.model.path),
|
||||
{ kind: "separator" },
|
||||
{
|
||||
kind: "action",
|
||||
action: "diff.compareWith",
|
||||
arg: slot.model.path,
|
||||
label: "Compare With…",
|
||||
},
|
||||
{
|
||||
kind: "action",
|
||||
action: "diff.compareWithClipboard",
|
||||
@@ -1598,6 +1604,9 @@ export class EditorController implements SlotHost {
|
||||
localHistoryMenu(path),
|
||||
...(inProject ? [gitMenu(path)] : []),
|
||||
{ kind: "separator" },
|
||||
{ kind: "action", action: "diff.compareWith", arg: path, label: "Compare With…" },
|
||||
{ kind: "action", action: "diff.compareWithClipboard", arg: { path }, label: "Compare with Clipboard" },
|
||||
{ kind: "separator" },
|
||||
{
|
||||
label: "Copy Path/Reference…",
|
||||
submenu: [
|
||||
|
||||
@@ -177,6 +177,17 @@ describe("project view context menu", () => {
|
||||
expect(l).not.toContain("Compare With…");
|
||||
});
|
||||
|
||||
it("offers Compare With… in a non-git project too", () => {
|
||||
useProject.setState({
|
||||
project: { name: "p", root: ROOT, isGit: false, settings: {} } as never,
|
||||
settings: {} as never,
|
||||
});
|
||||
const l = labels(contextMenuItems([node(`${ROOT}/a.py`)]));
|
||||
expect(l).not.toContain("Git");
|
||||
expect(l).toContain("Compare With…");
|
||||
expect(labels(contextMenuItems([node(`${ROOT}/a.py`), node(`${ROOT}/b.py`)]))).toContain("Compare Files");
|
||||
});
|
||||
|
||||
it("never shows an empty submenu", () => {
|
||||
disposers.forEach((d) => d());
|
||||
disposers = [];
|
||||
|
||||
@@ -92,6 +92,34 @@ async function pickFile(near: string): Promise<string | null> {
|
||||
return (Array.isArray(picked) ? picked[0] : picked) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The file to compare `path` against: the OS file dialog on the desktop; a
|
||||
* browser file picker's contents elsewhere (remote development / `pnpm dev`),
|
||||
* compared as text since no absolute path is available to the backend.
|
||||
*/
|
||||
async function pickComparison(
|
||||
path: string,
|
||||
): Promise<{ type: "file"; path: string } | { type: "text"; text: string; label: string } | null> {
|
||||
if (isTauri()) {
|
||||
const picked = await pickFile(path);
|
||||
return picked ? { type: "file", path: picked } : null;
|
||||
}
|
||||
if (typeof document === "undefined") {
|
||||
info("Compare With needs the desktop app or a browser file picker");
|
||||
return null;
|
||||
}
|
||||
const chosen = await new Promise<File | null>((resolve) => {
|
||||
const input = document.createElement("input");
|
||||
input.type = "file";
|
||||
input.onchange = () => resolve(input.files?.[0] ?? null);
|
||||
// Chrome fires `cancel` (or focus returns) when the dialog is dismissed.
|
||||
input.addEventListener("cancel", () => resolve(null));
|
||||
input.click();
|
||||
});
|
||||
if (!chosen) return null;
|
||||
return { type: "text", text: await chosen.text(), label: chosen.name };
|
||||
}
|
||||
|
||||
const contextPath = (arg: unknown) => argPath(arg) ?? maybeEditorService()?.activePath() ?? undefined;
|
||||
|
||||
export function registerCompareActions(): () => void {
|
||||
@@ -186,9 +214,18 @@ export function registerCompareActions(): () => void {
|
||||
run: async ({ arg }) => {
|
||||
const path = contextPath(arg);
|
||||
if (!path) return info("Open or select a file to compare");
|
||||
const other = await pickFile(path);
|
||||
if (!other || other === path) return;
|
||||
await openDiff(compareFilesData(path, other));
|
||||
const other = await pickComparison(path);
|
||||
if (!other) return;
|
||||
if (other.type === "file") {
|
||||
if (other.path === path) return;
|
||||
await openDiff(compareFilesData(path, other.path));
|
||||
} else {
|
||||
await openDiff({
|
||||
path,
|
||||
left: { type: "text", text: other.text, label: other.label },
|
||||
right: { type: "worktree", label: displayPath(path) },
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user