feat: edit in the Changes panel, git graph history, plan quota (v2.3.0)
- Changes panel: a working file opens in a CodeMirror editor with its diff inline (DiffEditor.tsx, @codemirror/merge, lazy-loaded); Changes folds the unchanged lines, Whole file shows them; side by side at 50/50 and full width; a Revert per block; original from HEAD or the branch's merge base (`mergeBase` on GET /git/changes?range=branch) - Every diff: green = line added whole, red = removed whole, blue = edited in place (--diff-mod) - History drawn as a commit graph (#58: `parents` on GET /git/log, --date-order; lib/commitGraph.ts) - Per-workspace never-stage list, drawn orange in the Files tree (--kept); closed Terminal rows past three deleted - Status bar plan quota for Claude (per account) and Codex (GET /api/pricing/quota, server/lib/quota.js); compact hover panel that stays open, Refresh button with a spinner - Settings → Appearance holds language, theme and pet; Ctrl+Shift+C copies; compact sidebar navigation and short session times
This commit is contained in:
+14
-5
@@ -508,7 +508,7 @@ async function synthesizeAddedPatch(dir, file) {
|
||||
* `file` is set, which is already a full read of one file.
|
||||
* @param {number} [opts.context] Unchanged lines around each hunk. The panel
|
||||
* raises this to expand a diff towards the whole file.
|
||||
* @returns {Promise<{range, base, baseRef, sha, context, files, truncated}>}
|
||||
* @returns {Promise<{range, base, baseRef, mergeBase, sha, context, files, truncated}>}
|
||||
*/
|
||||
async function collectChanges(
|
||||
dir,
|
||||
@@ -520,11 +520,17 @@ async function collectChanges(
|
||||
const ctx = normalizeContext(context);
|
||||
|
||||
let baseRef = null;
|
||||
// The commit a branch diff is taken from (`<baseRef>...HEAD`): the editor
|
||||
// reads a file's original text there.
|
||||
let mergeBase = null;
|
||||
if (range === "branch") {
|
||||
baseRef = await resolveBaseRef(dir, base);
|
||||
if (!baseRef) {
|
||||
throw badRequest("ENOBASE", "no base branch to compare against");
|
||||
}
|
||||
mergeBase = await git(dir, ["merge-base", baseRef, "HEAD"])
|
||||
.then((r) => r.stdout.trim() || null)
|
||||
.catch(() => null);
|
||||
}
|
||||
if (range === "commit") {
|
||||
if (!sha || !SAFE_REV.test(sha)) throw badRequest("EBADREV", "sha is not a valid revision");
|
||||
@@ -598,7 +604,7 @@ async function collectChanges(
|
||||
}
|
||||
}
|
||||
|
||||
return { range, base, baseRef, sha, context: ctx, files, truncated };
|
||||
return { range, base, baseRef, mergeBase, sha, context: ctx, files, truncated };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -615,8 +621,10 @@ async function collectChanges(
|
||||
*/
|
||||
async function listCommits(dir, { limit = 30, file = null } = {}) {
|
||||
const n = Math.min(Math.max(Number(limit) || 30, 1), 200);
|
||||
const format = ["%H", "%h", "%s", "%an", "%aI", "%D"].join("%x1f");
|
||||
const args = ["log", `-${n}`, `--format=${format}%x1e`];
|
||||
const format = ["%H", "%h", "%s", "%an", "%aI", "%D", "%P"].join("%x1f");
|
||||
// --date-order: no parent before all its children, which the history's
|
||||
// commit graph needs to draw a lane down to each parent.
|
||||
const args = ["log", `-${n}`, "--date-order", `--format=${format}%x1e`];
|
||||
// Through the same lexical guard as every other path: in a subdirectory
|
||||
// lane `../x` would list commit metadata for a path outside the lane.
|
||||
if (file) args.push("--", lanePath(file));
|
||||
@@ -625,7 +633,7 @@ async function listCommits(dir, { limit = 30, file = null } = {}) {
|
||||
for (const record of result.stdout.split("\x1e")) {
|
||||
const line = record.replace(/^\n/, "");
|
||||
if (!line.trim()) continue;
|
||||
const [sha, short, subject, author, date, refs] = line.split("\x1f");
|
||||
const [sha, short, subject, author, date, refs, parents] = line.split("\x1f");
|
||||
commits.push({
|
||||
sha,
|
||||
short,
|
||||
@@ -638,6 +646,7 @@ async function listCommits(dir, { limit = 30, file = null } = {}) {
|
||||
.split(", ")
|
||||
.map((r) => r.trim())
|
||||
.filter(Boolean),
|
||||
parents: (parents || "").split(" ").filter(Boolean),
|
||||
});
|
||||
}
|
||||
return commits;
|
||||
|
||||
Reference in New Issue
Block a user