feat(github): pull request tool window, timeline and review flow (#477)

Replaces the Pull Requests tool window with a full review workflow on top of gh's authentication.

- List with search, quick filters and paging; a tab per pull request and a New Pull Request tab.
- Details: commit picker, changes tree with viewed state, CI and reviewer status, merge, close and reopen.
- Timeline editor: comments, review threads, reactions and suggested changes.
- Review in the diff viewer and, for the checked-out branch, in the editor (review mode).
- New generic vcs extension points: registerDiffViewerProvider, lineInlays, reviewGutter, branch widget extensions; new vcs_merge_base and gh_api commands.
- CSP: img-src allows https://avatars.githubusercontent.com for avatars.

Fixed while testing against a real repository: remotes behind an SSH host alias, mergeability stuck on UNKNOWN, Apply Locally staying disabled after a checkout, relative links navigating the app's page, and review inlays wider than the pane.

Co-authored-by: imacross <[email protected]>
Цей коміт міститься в:
imacross authored and GitHub committed 2026-10-31 07:50:43 +08:00
1 джерело 696377acc2
коміт 059fd8a69b
192 files changed
+23668 -2076

No files matched your search

+27
Переглянути файл
@@ -276,6 +276,33 @@ export class LaneMarker extends GutterMarker {
}
}
/**
* The floating row at the editor's top-right (IDEA's inspection widget area): widgets
* append their element to it (CSS `order` sorts them; lower first) and remove it when
* done. The inspection widget sits there; code review adds its Review Mode group.
*
* const el = document.createElement("div");
* el.style.order = "-1";
* editorCorner(view).appendChild(el);
*/
export function editorCorner(view: EditorView): HTMLElement {
const found = view.dom.querySelector<HTMLElement>(":scope > .cm-openidea-corner");
if (found) return found;
const el = document.createElement("div");
el.className = "cm-openidea-corner";
Object.assign(el.style, {
position: "absolute",
top: "4px",
right: "16px",
zIndex: "5",
display: "flex",
alignItems: "center",
gap: "4px",
});
view.dom.appendChild(el);
return el;
}
// --- language support without a language server ----------------------------------
/**
+2 -5
Переглянути файл
@@ -6,6 +6,7 @@
import { EditorView, ViewPlugin, type ViewUpdate } from "@codemirror/view";
import { forEachDiagnostic } from "@codemirror/lint";
import { shortcutLabel } from "@/platform/keymap";
import { editorCorner } from "@/editor/api";
import { toolWindowService } from "@/workbench/contributions";
import { gotoDiagnostic } from "./diagnostics";
import { iconNode } from "./iconMarkup";
@@ -50,7 +51,7 @@ class InspectionWidget {
this.dom.className = "cm-openidea-inspection";
this.dom.setAttribute("role", "toolbar");
this.dom.setAttribute("aria-label", "Inspections");
view.dom.appendChild(this.dom);
editorCorner(view).appendChild(this.dom);
this.render();
}
@@ -123,10 +124,6 @@ const inspectionPlugin = ViewPlugin.fromClass(InspectionWidget);
const inspectionTheme = EditorView.theme({
".cm-openidea-inspection": {
position: "absolute",
top: "4px",
right: "16px",
zIndex: "5",
display: "flex",
alignItems: "center",
gap: "1px",