@civilization/dsh-experimental-git 0.0.0-stage → 0.2.1-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.i18n.yaml +13 -0
- package/README.md +22 -2
- package/README.zh.md +23 -0
- package/cordis.patch.yml +3 -0
- package/icon.svg +26 -0
- package/lib/client.js +2836 -0
- package/lib/index.js +7623 -0
- package/lib/types/client/GitBody.d.ts +66 -0
- package/lib/types/client/GitBranchPill.d.ts +27 -0
- package/lib/types/client/GitTitle.d.ts +12 -0
- package/lib/types/client/definition.d.ts +19 -0
- package/lib/types/client/git-helpers.d.ts +65 -0
- package/lib/types/client/index.d.ts +16 -0
- package/lib/types/client/locales.d.ts +185 -0
- package/lib/types/git-executor.d.ts +151 -0
- package/lib/types/index.d.ts +17 -0
- package/lib/types/tool.d.ts +11 -0
- package/lib/types/types.d.ts +175 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +75 -3
package/lib/client.js
ADDED
|
@@ -0,0 +1,2836 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "@civilization/dsh-experimental-git",
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
var module = { exports: {} };
|
|
5
|
+
var exports = module.exports;
|
|
6
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
|
+
let react = require("react");
|
|
9
|
+
let react_dom = require("react-dom");
|
|
10
|
+
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
11
|
+
/** Implementation identity in the tab system */
|
|
12
|
+
const GIT_ID = "@deepseek-ai/dsh-experimental-git";
|
|
13
|
+
/** Git artwork for the Sidebar Guide */
|
|
14
|
+
function GuideArtworkGit() {
|
|
15
|
+
return (0, react_jsx_runtime.jsxs)("svg", {
|
|
16
|
+
width: "40",
|
|
17
|
+
height: "40",
|
|
18
|
+
viewBox: "0 0 36 36",
|
|
19
|
+
fill: "none",
|
|
20
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
21
|
+
children: [
|
|
22
|
+
(0, react_jsx_runtime.jsx)("line", {
|
|
23
|
+
x1: "12",
|
|
24
|
+
y1: "9",
|
|
25
|
+
x2: "12",
|
|
26
|
+
y2: "27",
|
|
27
|
+
stroke: "#F05133",
|
|
28
|
+
strokeWidth: "2.5",
|
|
29
|
+
strokeLinecap: "round"
|
|
30
|
+
}),
|
|
31
|
+
(0, react_jsx_runtime.jsx)("path", {
|
|
32
|
+
d: "M12 21C12 18 15 15 18 15H22C23.5 15 24 14.5 24 13V12",
|
|
33
|
+
stroke: "#F05133",
|
|
34
|
+
strokeWidth: "2.5",
|
|
35
|
+
strokeLinecap: "round",
|
|
36
|
+
fill: "none"
|
|
37
|
+
}),
|
|
38
|
+
(0, react_jsx_runtime.jsx)("circle", {
|
|
39
|
+
cx: "12",
|
|
40
|
+
cy: "26",
|
|
41
|
+
r: "3.5",
|
|
42
|
+
fill: "#FFFFFF",
|
|
43
|
+
stroke: "#F05133",
|
|
44
|
+
strokeWidth: "2.5"
|
|
45
|
+
}),
|
|
46
|
+
(0, react_jsx_runtime.jsx)("circle", {
|
|
47
|
+
cx: "12",
|
|
48
|
+
cy: "10",
|
|
49
|
+
r: "3.5",
|
|
50
|
+
fill: "#FFFFFF",
|
|
51
|
+
stroke: "#F05133",
|
|
52
|
+
strokeWidth: "2.5"
|
|
53
|
+
}),
|
|
54
|
+
(0, react_jsx_runtime.jsx)("circle", {
|
|
55
|
+
cx: "24",
|
|
56
|
+
cy: "11",
|
|
57
|
+
r: "3.5",
|
|
58
|
+
fill: "#FFFFFF",
|
|
59
|
+
stroke: "#3680F6",
|
|
60
|
+
strokeWidth: "2.5"
|
|
61
|
+
})
|
|
62
|
+
]
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Tab definition for the Git right-sidebar viewer.
|
|
67
|
+
* @param t - namespace-bound translation function.
|
|
68
|
+
* @returns Complete sidebar tab definition.
|
|
69
|
+
*/
|
|
70
|
+
function gitDefinition(t) {
|
|
71
|
+
return {
|
|
72
|
+
id: GIT_ID,
|
|
73
|
+
kind: "git",
|
|
74
|
+
priority: "builtin",
|
|
75
|
+
title: () => t("type.label"),
|
|
76
|
+
guide: [{
|
|
77
|
+
id: "git",
|
|
78
|
+
commandId: "workspace.git",
|
|
79
|
+
order: 15,
|
|
80
|
+
title: () => t("guide.title"),
|
|
81
|
+
description: () => t("guide.description"),
|
|
82
|
+
icon: GuideArtworkGit
|
|
83
|
+
}]
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region lib/types/client/git-helpers.js
|
|
88
|
+
/**
|
|
89
|
+
* Conventional Commits and presentation helpers for Git commits and avatars.
|
|
90
|
+
*/
|
|
91
|
+
/**
|
|
92
|
+
* Parse conventional commit prefix from a commit subject.
|
|
93
|
+
* @param subject - Raw first line of commit message.
|
|
94
|
+
* @returns Parsed type, scope, and clean subject.
|
|
95
|
+
*/
|
|
96
|
+
function parseConventionalCommit(subject) {
|
|
97
|
+
const trimmed = subject.trim();
|
|
98
|
+
if (/^merge\s+(pull\s+request|branch|remote-tracking\s+branch)/i.test(trimmed)) return {
|
|
99
|
+
type: "merge",
|
|
100
|
+
cleanSubject: trimmed
|
|
101
|
+
};
|
|
102
|
+
const match = /^(feat|fix|style|refactor|docs|test|chore|release|revert)(?:\(([^)]+)\))?!?:\s*(.*)$/i.exec(trimmed);
|
|
103
|
+
if (match && match[1]) {
|
|
104
|
+
const rawType = match[1].toLowerCase();
|
|
105
|
+
const scope = match[2]?.trim();
|
|
106
|
+
return {
|
|
107
|
+
type: rawType,
|
|
108
|
+
...scope !== void 0 ? { scope } : {},
|
|
109
|
+
cleanSubject: trimmed
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
return { cleanSubject: trimmed };
|
|
113
|
+
}
|
|
114
|
+
const AVATAR_PALETTE = [
|
|
115
|
+
"#388bfd",
|
|
116
|
+
"#2ea043",
|
|
117
|
+
"#f0883e",
|
|
118
|
+
"#a371f7",
|
|
119
|
+
"#db61a2",
|
|
120
|
+
"#39c5bb",
|
|
121
|
+
"#f9c513",
|
|
122
|
+
"#6f42c1"
|
|
123
|
+
];
|
|
124
|
+
/**
|
|
125
|
+
* Deterministically compute avatar initial and background color for an author name.
|
|
126
|
+
* @param author - Author name or email.
|
|
127
|
+
* @returns Initial letter and hex color code.
|
|
128
|
+
*/
|
|
129
|
+
function getAuthorAvatar(author) {
|
|
130
|
+
const clean = author.trim();
|
|
131
|
+
const initial = clean.length > 0 ? clean[0]?.toUpperCase() ?? "?" : "?";
|
|
132
|
+
let hash = 0;
|
|
133
|
+
for (let i = 0; i < clean.length; i++) {
|
|
134
|
+
hash = (hash << 5) - hash + clean.charCodeAt(i);
|
|
135
|
+
hash |= 0;
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
initial,
|
|
139
|
+
color: AVATAR_PALETTE[Math.abs(hash) % AVATAR_PALETTE.length] ?? "#388bfd"
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Format date string into YYYY-MM-DD HH:mm:ss.
|
|
144
|
+
* @param dateStr - ISO or Git date string.
|
|
145
|
+
* @returns Clean formatted local date and time string.
|
|
146
|
+
*/
|
|
147
|
+
function formatFullDate(dateStr) {
|
|
148
|
+
const d = new Date(dateStr);
|
|
149
|
+
if (Number.isNaN(d.getTime())) return dateStr;
|
|
150
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
151
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
|
|
152
|
+
}
|
|
153
|
+
const GRAPH_LANE_PALETTE = [
|
|
154
|
+
"#388bfd",
|
|
155
|
+
"#3fb950",
|
|
156
|
+
"#f0883e",
|
|
157
|
+
"#a371f7",
|
|
158
|
+
"#58a6ff",
|
|
159
|
+
"#bc8cff",
|
|
160
|
+
"#db61a2",
|
|
161
|
+
"#2ea043"
|
|
162
|
+
];
|
|
163
|
+
const ROW_HEIGHT = 28;
|
|
164
|
+
const LANE_WIDTH = 16;
|
|
165
|
+
const LANE_X_OFFSET = 10;
|
|
166
|
+
/**
|
|
167
|
+
* Compute global continuous SVG DAG topology graph for commit items (IntelliJ IDEA grade).
|
|
168
|
+
* Eliminates per-row segmentation gaps, floating nodes, and misaligned curves.
|
|
169
|
+
* @param commits - Ordered commit items.
|
|
170
|
+
* @returns Fully computed nodes, edges, maxLane, and width.
|
|
171
|
+
*/
|
|
172
|
+
function computeDagGraph(commits) {
|
|
173
|
+
if (commits.length === 0) return {
|
|
174
|
+
nodes: [],
|
|
175
|
+
edges: [],
|
|
176
|
+
maxLane: 0,
|
|
177
|
+
graphWidth: 36
|
|
178
|
+
};
|
|
179
|
+
const hashToIndex = /* @__PURE__ */ new Map();
|
|
180
|
+
commits.forEach((c, idx) => hashToIndex.set(c.hash, idx));
|
|
181
|
+
const mainlineSet = /* @__PURE__ */ new Set();
|
|
182
|
+
let curr = commits.find((c) => c.refs?.some((r) => r.includes("HEAD") || r === "master" || r === "main"))?.hash ?? commits[0]?.hash;
|
|
183
|
+
while (curr && hashToIndex.has(curr)) {
|
|
184
|
+
mainlineSet.add(curr);
|
|
185
|
+
const commitIdx = hashToIndex.get(curr);
|
|
186
|
+
if (commitIdx === void 0) break;
|
|
187
|
+
const c = commits[commitIdx];
|
|
188
|
+
if (!c || !c.parents || c.parents.length === 0) break;
|
|
189
|
+
curr = c.parents[0];
|
|
190
|
+
}
|
|
191
|
+
const activeLanes = [null];
|
|
192
|
+
const commitLanes = Array.from({ length: commits.length }, () => 0);
|
|
193
|
+
commits.forEach((c, idx) => {
|
|
194
|
+
let lane = 0;
|
|
195
|
+
if (mainlineSet.has(c.hash)) {
|
|
196
|
+
lane = 0;
|
|
197
|
+
for (let l = 1; l < activeLanes.length; l++) if (activeLanes[l] === c.hash) activeLanes[l] = null;
|
|
198
|
+
} else {
|
|
199
|
+
let foundLane = -1;
|
|
200
|
+
for (let l = 1; l < activeLanes.length; l++) if (activeLanes[l] === c.hash) {
|
|
201
|
+
foundLane = l;
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
if (foundLane !== -1) {
|
|
205
|
+
lane = foundLane;
|
|
206
|
+
activeLanes[lane] = null;
|
|
207
|
+
} else {
|
|
208
|
+
let slot = -1;
|
|
209
|
+
for (let l = 1; l < activeLanes.length; l++) if (activeLanes[l] === null) {
|
|
210
|
+
slot = l;
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
if (slot !== -1) lane = slot;
|
|
214
|
+
else {
|
|
215
|
+
lane = Math.max(1, activeLanes.length);
|
|
216
|
+
while (activeLanes.length <= lane) activeLanes.push(null);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
commitLanes[idx] = lane;
|
|
221
|
+
if (c.parents && c.parents.length > 0) c.parents.forEach((parentHash, pIdx) => {
|
|
222
|
+
if (mainlineSet.has(parentHash)) return;
|
|
223
|
+
if (activeLanes.includes(parentHash)) return;
|
|
224
|
+
if (pIdx === 0 && lane >= 1 && activeLanes[lane] === null) activeLanes[lane] = parentHash;
|
|
225
|
+
else {
|
|
226
|
+
let slot = -1;
|
|
227
|
+
for (let l = 1; l < activeLanes.length; l++) if (activeLanes[l] === null) {
|
|
228
|
+
slot = l;
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
if (slot !== -1) activeLanes[slot] = parentHash;
|
|
232
|
+
else activeLanes.push(parentHash);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
while (activeLanes.length > 1 && activeLanes.at(-1) === null) activeLanes.pop();
|
|
236
|
+
});
|
|
237
|
+
const maxLane = Math.max(0, ...commitLanes);
|
|
238
|
+
const edges = [];
|
|
239
|
+
const processedEdges = /* @__PURE__ */ new Set();
|
|
240
|
+
commits.forEach((c, idx) => {
|
|
241
|
+
const fromLane = commitLanes[idx] ?? 0;
|
|
242
|
+
const x1 = fromLane * LANE_WIDTH + LANE_X_OFFSET;
|
|
243
|
+
const y1 = idx * ROW_HEIGHT + ROW_HEIGHT / 2;
|
|
244
|
+
const nodeColor = GRAPH_LANE_PALETTE[fromLane % GRAPH_LANE_PALETTE.length] ?? "#388bfd";
|
|
245
|
+
if (!c.parents || c.parents.length === 0) return;
|
|
246
|
+
c.parents.forEach((pHash) => {
|
|
247
|
+
const edgeKey = `${c.hash}->${pHash}`;
|
|
248
|
+
if (processedEdges.has(edgeKey)) return;
|
|
249
|
+
processedEdges.add(edgeKey);
|
|
250
|
+
const pIdxInList = hashToIndex.get(pHash);
|
|
251
|
+
if (pIdxInList !== void 0) {
|
|
252
|
+
const toLane = commitLanes[pIdxInList] ?? 0;
|
|
253
|
+
const x2 = toLane * LANE_WIDTH + LANE_X_OFFSET;
|
|
254
|
+
const y2 = pIdxInList * ROW_HEIGHT + ROW_HEIGHT / 2;
|
|
255
|
+
const edgeColor = fromLane > 0 ? nodeColor : toLane > 0 ? GRAPH_LANE_PALETTE[toLane % GRAPH_LANE_PALETTE.length] ?? nodeColor : nodeColor;
|
|
256
|
+
if (x1 === x2) edges.push({
|
|
257
|
+
key: edgeKey,
|
|
258
|
+
fromHash: c.hash,
|
|
259
|
+
toHash: pHash,
|
|
260
|
+
color: edgeColor,
|
|
261
|
+
d: `M ${x1} ${y1} L ${x2} ${y2}`
|
|
262
|
+
});
|
|
263
|
+
else if (pIdxInList === idx + 1) edges.push({
|
|
264
|
+
key: edgeKey,
|
|
265
|
+
fromHash: c.hash,
|
|
266
|
+
toHash: pHash,
|
|
267
|
+
color: edgeColor,
|
|
268
|
+
d: `M ${x1} ${y1} C ${x1} ${y1 + 14}, ${x2} ${y2 - 14}, ${x2} ${y2}`
|
|
269
|
+
});
|
|
270
|
+
else if (toLane === 0) edges.push({
|
|
271
|
+
key: edgeKey,
|
|
272
|
+
fromHash: c.hash,
|
|
273
|
+
toHash: pHash,
|
|
274
|
+
color: edgeColor,
|
|
275
|
+
d: `M ${x1} ${y1} L ${x1} ${y2 - 28} C ${x1} ${y2 - 14}, ${x2} ${y2 - 14}, ${x2} ${y2}`
|
|
276
|
+
});
|
|
277
|
+
else edges.push({
|
|
278
|
+
key: edgeKey,
|
|
279
|
+
fromHash: c.hash,
|
|
280
|
+
toHash: pHash,
|
|
281
|
+
color: edgeColor,
|
|
282
|
+
d: `M ${x1} ${y1} C ${x1} ${y1 + 14}, ${x2} ${y1 + 14}, ${x2} ${y1 + 28} L ${x2} ${y2}`
|
|
283
|
+
});
|
|
284
|
+
} else {
|
|
285
|
+
const bottomY = commits.length * ROW_HEIGHT;
|
|
286
|
+
edges.push({
|
|
287
|
+
key: edgeKey,
|
|
288
|
+
fromHash: c.hash,
|
|
289
|
+
color: nodeColor,
|
|
290
|
+
d: `M ${x1} ${y1} L ${x1} ${bottomY}`
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
return {
|
|
296
|
+
nodes: commits.map((c, idx) => {
|
|
297
|
+
const lane = commitLanes[idx] ?? 0;
|
|
298
|
+
const x = lane * LANE_WIDTH + LANE_X_OFFSET;
|
|
299
|
+
const y = idx * ROW_HEIGHT + ROW_HEIGHT / 2;
|
|
300
|
+
const color = GRAPH_LANE_PALETTE[lane % GRAPH_LANE_PALETTE.length] ?? "#388bfd";
|
|
301
|
+
const isHead = Boolean(c.refs?.some((r) => r.includes("HEAD") || r === "master" || r === "main"));
|
|
302
|
+
const hasTag = Boolean(c.refs?.some((r) => r.startsWith("tag: ") || r.includes("tag:")));
|
|
303
|
+
return {
|
|
304
|
+
hash: c.hash,
|
|
305
|
+
lane,
|
|
306
|
+
color,
|
|
307
|
+
x,
|
|
308
|
+
y,
|
|
309
|
+
isHead,
|
|
310
|
+
hasTag
|
|
311
|
+
};
|
|
312
|
+
}),
|
|
313
|
+
edges,
|
|
314
|
+
maxLane,
|
|
315
|
+
graphWidth: Math.max(36, (maxLane + 1) * LANE_WIDTH + 16)
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
//#endregion
|
|
319
|
+
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/experimental/git/src/client/GitBody.module.css.mjs
|
|
320
|
+
const css$1 = ".n1ttEW_root{height:100%;min-height:0;color:var(--dsw-alias-label-primary);font-size:var(--dsh-content-font-size-secondary,13px);user-select:none;background:0 0;flex-direction:column;flex:auto;line-height:1.5;display:flex}.n1ttEW_header{box-sizing:border-box;border-bottom:.5px solid var(--dsw-alias-border-l2);flex:none;justify-content:space-between;align-items:center;gap:8px;height:38px;padding:0 10px 0 12px;display:flex}.n1ttEW_branchInfo{align-items:center;gap:6px;min-width:0;display:flex}.n1ttEW_branchBadge{border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;align-items:center;gap:4px;max-width:160px;padding:2px 7px;font-size:12px;font-weight:500;display:inline-flex;overflow:hidden}.n1ttEW_branchIcon{color:var(--dsw-alias-state-business-primary);flex-shrink:0}.n1ttEW_statusAheadBehind{gap:4px;font-size:11px;font-weight:600;display:inline-flex}.n1ttEW_aheadText{color:var(--dsw-alias-state-business-primary)}.n1ttEW_behindText{color:var(--dsw-alias-state-warn-primary)}.n1ttEW_headerActions{align-items:center;gap:4px;display:flex}.n1ttEW_iconButton{border-radius:var(--dsw-radius-sm);width:26px;height:26px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;justify-content:center;align-items:center;padding:0;transition:background-color .15s,color .15s;display:inline-flex}.n1ttEW_iconButton:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.n1ttEW_iconButton.n1ttEW_spinning svg{animation:.8s linear infinite n1ttEW_spin}@keyframes n1ttEW_spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.n1ttEW_tabs{border-bottom:.5px solid var(--dsw-alias-border-l2);background:0 0;align-items:center;gap:4px;padding:4px 10px;display:flex}.n1ttEW_tab{border-radius:var(--dsw-radius-sm);color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;align-items:center;gap:5px;padding:4px 10px;font-size:12px;font-weight:500;transition:all .15s;display:inline-flex}.n1ttEW_tab:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.n1ttEW_tabActive{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-state-business-primary);font-weight:600}.n1ttEW_tabCount{background:var(--dsw-alias-interactive-bg-hover);color:inherit;border-radius:10px;justify-content:center;align-items:center;padding:0 5px;font-size:10px;font-weight:700;display:inline-flex}.n1ttEW_content{flex-direction:column;flex:auto;gap:10px;min-height:0;padding:8px 10px;display:flex;overflow-y:auto}.n1ttEW_emptyState{text-align:center;color:var(--dsw-alias-label-tertiary);flex-direction:column;justify-content:center;align-items:center;gap:8px;padding:32px 16px;display:flex}.n1ttEW_emptyState svg{opacity:.6;width:28px;height:28px}.n1ttEW_section{border-radius:var(--dsw-radius-md);border:.5px solid var(--dsw-alias-border-l2);background:0 0;flex-direction:column;display:flex;overflow:hidden}.n1ttEW_sectionHeader{border-bottom:.5px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-interactive-bg-hover);cursor:pointer;color:var(--dsw-alias-label-primary);justify-content:space-between;align-items:center;padding:6px 10px;font-size:12px;font-weight:600;display:flex}.n1ttEW_sectionTitle{align-items:center;gap:6px;display:flex}.n1ttEW_sectionActions{align-items:center;gap:4px;display:flex}.n1ttEW_actionTextBtn{border-radius:var(--dsw-radius-xs,3px);border:.5px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;padding:2px 6px;font-size:11px;transition:all .12s}.n1ttEW_actionTextBtn:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.n1ttEW_fileList{flex-direction:column;display:flex}.n1ttEW_fileItem{border-top:.5px solid var(--dsw-alias-border-l1);cursor:pointer;color:var(--dsw-alias-label-primary);justify-content:space-between;align-items:center;padding:5px 10px;font-size:12px;transition:background .12s;display:flex}.n1ttEW_fileItem:hover{background:var(--dsw-alias-interactive-bg-hover)}.n1ttEW_fileLeft{flex:1;align-items:center;gap:6px;min-width:0;display:flex}.n1ttEW_statusBadge{border-radius:3px;flex-shrink:0;justify-content:center;align-items:center;width:16px;height:16px;font-size:10px;font-weight:700;display:inline-flex}.n1ttEW_statusM{background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 15%, transparent);color:var(--dsw-alias-state-business-primary)}.n1ttEW_statusA{background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 15%, transparent);color:var(--dsw-alias-state-success-primary)}.n1ttEW_statusD{background:color-mix(in srgb, var(--dsw-alias-state-error-primary) 15%, transparent);color:var(--dsw-alias-state-error-primary)}.n1ttEW_statusU{background:color-mix(in srgb, var(--dsw-alias-state-warn-primary) 15%, transparent);color:var(--dsw-alias-state-warn-primary)}.n1ttEW_fileName{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.n1ttEW_fileDir{color:var(--dsw-alias-label-tertiary);font-size:11px}.n1ttEW_fileItemActions{opacity:0;align-items:center;gap:4px;transition:opacity .12s;display:flex}.n1ttEW_fileItem:hover .n1ttEW_fileItemActions{opacity:1}.n1ttEW_fileMiniBtn{border-radius:var(--dsw-radius-xs,3px);background:var(--dsw-alias-interactive-bg-hover);width:20px;height:20px;color:var(--dsw-alias-label-secondary);cursor:pointer;border:none;justify-content:center;align-items:center;font-size:12px;transition:background .12s,color .12s;display:inline-flex}.n1ttEW_fileMiniBtn:hover{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-primary)}.n1ttEW_commitBox{border-radius:var(--dsw-radius-md);border:.5px solid var(--dsw-alias-border-l2);background:0 0;flex-direction:column;gap:8px;margin-top:4px;padding:10px;display:flex}.n1ttEW_commitTextarea{box-sizing:border-box;border-radius:var(--dsw-radius-sm);border:.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-interactive-bg-hover);width:100%;min-height:54px;max-height:120px;color:var(--dsw-alias-label-primary);resize:vertical;outline:none;padding:6px 8px;font-family:inherit;font-size:12px}.n1ttEW_commitTextarea:focus{border-color:var(--dsw-alias-state-business-primary)}.n1ttEW_commitButtonRow{justify-content:flex-end;align-items:center;gap:6px;display:flex}.n1ttEW_commitBtn{border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-state-success-primary);color:var(--dsw-alias-label-primary-inverted);cursor:pointer;border:none;align-items:center;gap:4px;padding:4px 12px;font-size:12px;font-weight:600;transition:background .15s;display:inline-flex}.n1ttEW_commitBtn:hover{background:var(--dsw-alias-state-success-secondary)}.n1ttEW_commitPushBtn{border-radius:var(--dsw-radius-sm);border:.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary);cursor:pointer;align-items:center;gap:4px;padding:4px 12px;font-size:12px;font-weight:500;transition:all .15s;display:inline-flex}.n1ttEW_commitPushBtn:hover{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-primary)}.n1ttEW_treeContainer{flex-direction:column;gap:0;min-height:0;display:flex;position:relative}.n1ttEW_treeRow{border-radius:var(--dsw-radius-sm);cursor:pointer;height:28px;color:var(--dsw-alias-label-primary);user-select:none;align-items:center;padding:0 6px;font-size:12px;transition:background .12s;display:flex}.n1ttEW_treeRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.n1ttEW_treeRowSelected{color:var(--dsw-alias-state-business-primary);background:var(--dsw-alias-interactive-bg-active)!important}.n1ttEW_graphSvg{flex-shrink:0;height:28px;margin-right:6px}.n1ttEW_graphOverlaySvg{pointer-events:none;z-index:1;position:absolute;top:0;left:10px}.n1ttEW_treeBody{flex:1;align-items:center;gap:6px;min-width:0;display:flex}.n1ttEW_refBadge{white-space:nowrap;border-radius:10px;flex-shrink:0;align-items:center;padding:1px 5px;font-size:10px;font-weight:700;line-height:12px;display:inline-flex}.n1ttEW_refHead{background:color-mix(in srgb, var(--dsw-alias-state-warn-primary) 18%, transparent);color:var(--dsw-alias-state-warn-primary);border:.5px solid var(--dsw-alias-state-warn-primary)}.n1ttEW_refBranch{background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 18%, transparent);color:var(--dsw-alias-state-success-primary);border:.5px solid var(--dsw-alias-state-success-primary)}.n1ttEW_refRemote{background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 18%, transparent);color:var(--dsw-alias-state-business-primary);border:.5px solid var(--dsw-alias-state-business-primary)}.n1ttEW_treeSubject{text-overflow:ellipsis;white-space:nowrap;flex:1;font-weight:500;overflow:hidden}.n1ttEW_treeAuthor{color:var(--dsw-alias-label-tertiary);white-space:nowrap;text-overflow:ellipsis;flex-shrink:0;max-width:80px;font-size:11px;overflow:hidden}.n1ttEW_treeTime{color:var(--dsw-alias-label-tertiary);white-space:nowrap;flex-shrink:0;font-size:11px}.n1ttEW_treeHash{color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-interactive-bg-hover);border-radius:var(--dsw-radius-xs,3px);flex-shrink:0;padding:0 4px;font-family:monospace;font-size:11px}.n1ttEW_commitDetailPanel{border-radius:var(--dsw-radius-lg);border:.5px solid var(--dsw-alias-border-l2);background:var(--dsw-specific-menu);backdrop-filter:var(--dsw-menu-backdrop-filter);--dsw-elevation-stroke-color:var(--dsw-alias-border-l1);box-shadow:var(--dsw-elevation-prominent);color:var(--dsw-alias-label-primary);flex-direction:column;gap:8px;margin-top:8px;padding:12px;display:flex}.n1ttEW_detailHeader{border-bottom:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:4px;padding-bottom:8px;display:flex}.n1ttEW_detailSubject{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600}.n1ttEW_detailMetaRow{color:var(--dsw-alias-label-tertiary);justify-content:space-between;align-items:center;font-size:11px;display:flex}.n1ttEW_detailFilesList{flex-direction:column;gap:2px;max-height:180px;display:flex;overflow-y:auto}.n1ttEW_detailFileItem{border-radius:var(--dsw-radius-sm);cursor:pointer;color:var(--dsw-alias-label-primary);justify-content:space-between;align-items:center;padding:4px 6px;font-size:11px;transition:background .12s;display:flex}.n1ttEW_detailFileItem:hover{background:var(--dsw-alias-interactive-bg-hover)}.n1ttEW_numstat{gap:4px;font-family:monospace;font-size:10px;display:inline-flex}.n1ttEW_addStat{color:var(--dsw-alias-state-success-primary)}.n1ttEW_delStat{color:var(--dsw-alias-state-error-primary)}.n1ttEW_diffViewer{border-radius:var(--dsw-radius-md);background:var(--dsw-alias-markdown-code-block);border:.5px solid var(--dsw-alias-border-l2);max-height:260px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:6px;padding:8px;font-family:monospace;font-size:11px;display:flex;overflow:auto}.n1ttEW_diffLine{white-space:pre-wrap;word-break:break-all;line-height:16px}.n1ttEW_diffAdd{background:var(--dsw-alias-code-diff-added);color:var(--dsw-alias-state-success-primary)}.n1ttEW_diffDel{background:var(--dsw-alias-code-diff-deleted);color:var(--dsw-alias-state-error-primary)}.n1ttEW_diffHunk{background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 12%, transparent);color:var(--dsw-alias-state-business-primary);font-weight:600}.n1ttEW_refTag{color:#f0883e;background:#f0883e2e;border:.5px solid #f0883e}.n1ttEW_treeRowHighlighted{border-left:2px solid var(--dsw-alias-state-business-primary);animation:2.5s ease-out forwards n1ttEW_rowGlow}@keyframes n1ttEW_rowGlow{0%{background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 35%, transparent);box-shadow:inset 0 0 12px color-mix(in srgb, var(--dsw-alias-state-business-primary) 40%, transparent)}40%{background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 25%, transparent);box-shadow:inset 0 0 8px color-mix(in srgb, var(--dsw-alias-state-business-primary) 20%, transparent)}to{background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 12%, transparent);box-shadow:none}}.n1ttEW_locateGlowRing{transform-origin:50%;stroke:var(--dsw-alias-state-business-primary);stroke-width:2px;fill:none;animation:1.5s ease-in-out infinite n1ttEW_pulseRing}@keyframes n1ttEW_pulseRing{0%{r:6;opacity:1}50%{r:10;opacity:.4}to{r:12;opacity:0}}.n1ttEW_treeRowActions{opacity:0;align-items:center;gap:2px;margin-left:4px;transition:opacity .12s;display:flex}.n1ttEW_treeRow:hover .n1ttEW_treeRowActions{opacity:1}.n1ttEW_treeActionBtn{border-radius:var(--dsw-radius-xs,3px);background:var(--dsw-alias-interactive-bg-hover);height:18px;color:var(--dsw-alias-label-secondary);cursor:pointer;border:none;justify-content:center;align-items:center;padding:1px 4px;font-size:10px;transition:background .12s,color .12s;display:inline-flex}.n1ttEW_treeActionBtn:hover{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-primary)}.n1ttEW_tagList{flex-direction:column;gap:6px;display:flex}.n1ttEW_tagCard{border-radius:var(--dsw-radius-md);border:.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-interactive-bg-hover);flex-direction:column;gap:6px;padding:10px 12px;transition:border-color .15s,background .15s;display:flex}.n1ttEW_tagCard:hover{border-color:var(--dsw-alias-border-l1);background:var(--dsw-alias-interactive-bg-active)}.n1ttEW_tagCardHeader{justify-content:space-between;align-items:center;gap:8px;display:flex}.n1ttEW_tagTitleRow{flex:1;align-items:center;gap:8px;min-width:0;display:flex}.n1ttEW_tagName{color:var(--dsw-alias-state-business-primary);cursor:pointer;text-overflow:ellipsis;white-space:nowrap;font-size:13px;font-weight:600;overflow:hidden}.n1ttEW_tagName:hover{text-decoration:underline}.n1ttEW_tagShaPill{border-radius:var(--dsw-radius-xs,3px);background:color-mix(in srgb, var(--dsw-alias-label-primary) 8%, transparent);color:var(--dsw-alias-label-secondary);cursor:pointer;padding:1px 6px;font-family:monospace;font-size:11px}.n1ttEW_tagShaPill:hover{background:color-mix(in srgb, var(--dsw-alias-label-primary) 15%, transparent);color:var(--dsw-alias-label-primary)}.n1ttEW_tagAnnotatedBadge{color:#f0883e;background:#f0883e2e;border:.5px solid #f0883e;border-radius:8px;padding:1px 5px;font-size:10px;font-weight:600}.n1ttEW_tagActions{flex-shrink:0;align-items:center;gap:4px;display:flex}.n1ttEW_tagLocateBtn{border:.5px solid color-mix(in srgb, var(--dsw-alias-state-business-primary) 40%, transparent);border-radius:var(--dsw-radius-sm);background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 12%, transparent);color:var(--dsw-alias-state-business-primary);cursor:pointer;align-items:center;gap:4px;padding:3px 8px;font-size:11px;font-weight:600;transition:all .15s;display:inline-flex}.n1ttEW_tagLocateBtn:hover{background:var(--dsw-alias-state-business-primary);color:#fff}.n1ttEW_tagMessage{color:var(--dsw-alias-label-secondary);text-overflow:ellipsis;white-space:nowrap;font-size:12px;overflow:hidden}.n1ttEW_tagMetaFooter{color:var(--dsw-alias-label-tertiary);justify-content:space-between;align-items:center;margin-top:2px;font-size:11px;display:flex}.n1ttEW_tagAuthor{color:var(--dsw-alias-label-secondary);align-items:center;gap:4px;display:inline-flex}.n1ttEW_tagForm{border-radius:var(--dsw-radius-md);border:.5px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-interactive-bg-hover);flex-direction:column;gap:8px;padding:12px;display:flex}.n1ttEW_tagFormTitle{color:var(--dsw-alias-label-primary);font-size:12px;font-weight:600}.n1ttEW_tagFormActions{justify-content:flex-end;gap:6px;display:flex}.n1ttEW_treeFilterRow{border-bottom:.5px solid var(--dsw-alias-border-l2);background:0 0;flex-shrink:0;justify-content:space-between;align-items:center;gap:8px;padding:6px 12px;display:flex}.n1ttEW_treeSearchInput{border-radius:var(--dsw-radius-sm);border:.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-interactive-bg-hover);min-width:0;height:26px;color:var(--dsw-alias-label-primary);outline:none;flex:1;padding:0 8px;font-size:11px;transition:border-color .15s}.n1ttEW_treeSearchInput:focus{border-color:var(--dsw-alias-state-business-primary)}.n1ttEW_mainlineToggleGroup{border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-interactive-bg-hover);border:.5px solid var(--dsw-alias-border-l2);flex-shrink:0;align-items:center;padding:1px;display:inline-flex}.n1ttEW_mainlineToggleBtn{border-radius:var(--dsw-radius-xs,3px);color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:none;padding:2px 8px;font-size:11px;font-weight:500;transition:all .12s}.n1ttEW_mainlineToggleBtnActive{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-primary);font-weight:600}.n1ttEW_workstationLayout{flex:auto;min-height:0;display:flex;overflow:hidden;container-type:inline-size}.n1ttEW_tablePane{flex-direction:column;flex:auto;min-width:0;min-height:0;display:flex;overflow-y:auto}.n1ttEW_treeTableHeader{grid-template-columns:var(--git-graph-col-width,48px) minmax(200px, 1fr) 115px 90px 72px;border-bottom:.5px solid var(--dsw-alias-border-l2);background:color-mix(in srgb, var(--dsw-alias-label-primary) 3%, transparent);height:28px;color:var(--dsw-alias-label-tertiary);user-select:none;z-index:2;align-items:center;gap:8px;padding:0 10px;font-size:11px;font-weight:600;display:grid;position:sticky;top:0}.n1ttEW_colHeaderTitle{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.n1ttEW_treeRowGrid{box-sizing:border-box;grid-template-columns:var(--git-graph-col-width,48px) minmax(200px, 1fr) 115px 90px 72px;border-bottom:.5px solid color-mix(in srgb, var(--dsw-alias-border-l2) 40%, transparent);height:28px;min-height:28px;max-height:28px;color:var(--dsw-alias-label-primary);cursor:pointer;user-select:none;align-items:center;gap:8px;padding:0 10px;font-size:12px;transition:background .1s;display:grid}.n1ttEW_treeRowGrid:hover{background:var(--dsw-alias-interactive-bg-hover)}.n1ttEW_treeRowGridSelected{color:var(--dsw-alias-state-business-primary);background:var(--dsw-alias-interactive-bg-active)!important}.n1ttEW_subjectCol{align-items:center;gap:6px;min-width:0;display:flex;overflow:hidden}.n1ttEW_typeBadge{border-radius:var(--dsw-radius-xs,3px);text-transform:lowercase;flex-shrink:0;justify-content:center;align-items:center;height:16px;padding:0 5px;font-size:10px;font-weight:600;line-height:16px;display:inline-flex}.n1ttEW_typeFeat{color:#2ea043;background:#2ea04329;border:.5px solid #2ea04366}.n1ttEW_typeFix{color:#f85149;background:#f8514929;border:.5px solid #f8514966}.n1ttEW_typeStyle,.n1ttEW_typeRefactor{color:#8250df;background:#8250df29;border:.5px solid #8250df66}.n1ttEW_typeRelease{color:#388bfd;background:#388bfd29;border:.5px solid #388bfd66}.n1ttEW_typeMerge{color:#6f42c1;background:#6f42c129;border:.5px solid #6f42c166}.n1ttEW_typeTest{color:#d29922;background:#d2992229;border:.5px solid #d2992266}.n1ttEW_typeDocs{color:#39c5bb;background:#39c5bb29;border:.5px solid #39c5bb66}.n1ttEW_typeChore,.n1ttEW_typeRevert{background:color-mix(in srgb, var(--dsw-alias-label-secondary) 14%, transparent);color:var(--dsw-alias-label-secondary);border:.5px solid color-mix(in srgb, var(--dsw-alias-label-secondary) 30%, transparent)}.n1ttEW_authorCol{align-items:center;gap:6px;min-width:0;display:flex;overflow:hidden}.n1ttEW_authorAvatar{color:#fff;border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;width:16px;height:16px;font-size:9px;font-weight:700;display:inline-flex}.n1ttEW_authorNameText{color:var(--dsw-alias-label-secondary);white-space:nowrap;text-overflow:ellipsis;font-size:11px;overflow:hidden}.n1ttEW_timeCol{color:var(--dsw-alias-label-tertiary);white-space:nowrap;text-overflow:ellipsis;font-size:11px;overflow:hidden}.n1ttEW_shaCol{color:var(--dsw-alias-label-secondary);white-space:nowrap;font-family:monospace;font-size:11px}.n1ttEW_detailsPane{border-left:.5px solid var(--dsw-alias-border-l2);background:var(--dsw-specific-menu);width:330px;backdrop-filter:var(--dsw-menu-backdrop-filter);box-sizing:border-box;flex-direction:column;flex-shrink:0;display:flex;overflow-y:auto}.n1ttEW_detailsHeader{border-bottom:.5px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);letter-spacing:.5px;justify-content:space-between;align-items:center;padding:10px 12px;font-size:11px;font-weight:700;display:flex}.n1ttEW_detailsContent{flex-direction:column;gap:12px;padding:12px;display:flex}.n1ttEW_detailsSubject{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600;line-height:18px}.n1ttEW_detailsBody{color:var(--dsw-alias-label-secondary);white-space:pre-wrap;word-break:break-word;font-size:11px;line-height:16px}.n1ttEW_detailsSectionTitle{color:var(--dsw-alias-label-tertiary);letter-spacing:.5px;margin-bottom:4px;font-size:10px;font-weight:700}.n1ttEW_detailsMetaGrid{flex-direction:column;gap:6px;font-size:11px;display:flex}.n1ttEW_detailsMetaRow{justify-content:space-between;align-items:center;gap:8px;display:flex}.n1ttEW_detailsMetaLabel{color:var(--dsw-alias-label-tertiary);flex-shrink:0}.n1ttEW_detailsMetaVal{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;font-family:monospace;overflow:hidden}.n1ttEW_detailsParentLink{color:var(--dsw-alias-state-business-primary);cursor:pointer;font-family:monospace}.n1ttEW_detailsParentLink:hover{text-decoration:underline}.n1ttEW_detailsBottomActions{gap:8px;margin-top:8px;display:flex}.n1ttEW_treeStatusFooter{border-top:.5px solid var(--dsw-alias-border-l2);background:color-mix(in srgb, var(--dsw-alias-label-primary) 2%, transparent);height:26px;color:var(--dsw-alias-label-tertiary);user-select:none;flex-shrink:0;justify-content:space-between;align-items:center;padding:0 10px;font-size:11px;display:flex}.n1ttEW_footerSyncStatus{align-items:center;gap:6px;display:flex}.n1ttEW_syncDot{background:var(--dsw-alias-state-success-primary);border-radius:50%;width:6px;height:6px}.n1ttEW_footerStats{align-items:center;gap:8px;display:flex}.n1ttEW_loadMoreLink{color:var(--dsw-alias-state-business-primary);cursor:pointer;font-weight:500}.n1ttEW_loadMoreLink:hover{text-decoration:underline}@container (width<=680px){.n1ttEW_workstationLayout{flex-direction:column}.n1ttEW_tablePane{flex:auto;min-height:160px}.n1ttEW_detailsPane{border-top:.5px solid var(--dsw-alias-border-l2);flex-shrink:0;max-height:340px;border-left:none!important;width:100%!important}}";
|
|
321
|
+
const tagId$1 = "@civilization/dsh-experimental-git/GitBody.module.css";
|
|
322
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
323
|
+
const tag = document.createElement("style");
|
|
324
|
+
tag.dataset.plugin = "@civilization/dsh-experimental-git";
|
|
325
|
+
tag.dataset.pluginCss = tagId$1;
|
|
326
|
+
tag.textContent = css$1;
|
|
327
|
+
document.head.appendChild(tag);
|
|
328
|
+
}
|
|
329
|
+
var GitBody_module_css_default = {
|
|
330
|
+
"actionTextBtn": "n1ttEW_actionTextBtn",
|
|
331
|
+
"addStat": "n1ttEW_addStat",
|
|
332
|
+
"aheadText": "n1ttEW_aheadText",
|
|
333
|
+
"authorAvatar": "n1ttEW_authorAvatar",
|
|
334
|
+
"authorCol": "n1ttEW_authorCol",
|
|
335
|
+
"authorNameText": "n1ttEW_authorNameText",
|
|
336
|
+
"behindText": "n1ttEW_behindText",
|
|
337
|
+
"branchBadge": "n1ttEW_branchBadge",
|
|
338
|
+
"branchIcon": "n1ttEW_branchIcon",
|
|
339
|
+
"branchInfo": "n1ttEW_branchInfo",
|
|
340
|
+
"colHeaderTitle": "n1ttEW_colHeaderTitle",
|
|
341
|
+
"commitBox": "n1ttEW_commitBox",
|
|
342
|
+
"commitBtn": "n1ttEW_commitBtn",
|
|
343
|
+
"commitButtonRow": "n1ttEW_commitButtonRow",
|
|
344
|
+
"commitDetailPanel": "n1ttEW_commitDetailPanel",
|
|
345
|
+
"commitPushBtn": "n1ttEW_commitPushBtn",
|
|
346
|
+
"commitTextarea": "n1ttEW_commitTextarea",
|
|
347
|
+
"content": "n1ttEW_content",
|
|
348
|
+
"delStat": "n1ttEW_delStat",
|
|
349
|
+
"detailFileItem": "n1ttEW_detailFileItem",
|
|
350
|
+
"detailFilesList": "n1ttEW_detailFilesList",
|
|
351
|
+
"detailHeader": "n1ttEW_detailHeader",
|
|
352
|
+
"detailMetaRow": "n1ttEW_detailMetaRow",
|
|
353
|
+
"detailSubject": "n1ttEW_detailSubject",
|
|
354
|
+
"detailsBody": "n1ttEW_detailsBody",
|
|
355
|
+
"detailsBottomActions": "n1ttEW_detailsBottomActions",
|
|
356
|
+
"detailsContent": "n1ttEW_detailsContent",
|
|
357
|
+
"detailsHeader": "n1ttEW_detailsHeader",
|
|
358
|
+
"detailsMetaGrid": "n1ttEW_detailsMetaGrid",
|
|
359
|
+
"detailsMetaLabel": "n1ttEW_detailsMetaLabel",
|
|
360
|
+
"detailsMetaRow": "n1ttEW_detailsMetaRow",
|
|
361
|
+
"detailsMetaVal": "n1ttEW_detailsMetaVal",
|
|
362
|
+
"detailsPane": "n1ttEW_detailsPane",
|
|
363
|
+
"detailsParentLink": "n1ttEW_detailsParentLink",
|
|
364
|
+
"detailsSectionTitle": "n1ttEW_detailsSectionTitle",
|
|
365
|
+
"detailsSubject": "n1ttEW_detailsSubject",
|
|
366
|
+
"diffAdd": "n1ttEW_diffAdd",
|
|
367
|
+
"diffDel": "n1ttEW_diffDel",
|
|
368
|
+
"diffHunk": "n1ttEW_diffHunk",
|
|
369
|
+
"diffLine": "n1ttEW_diffLine",
|
|
370
|
+
"diffViewer": "n1ttEW_diffViewer",
|
|
371
|
+
"emptyState": "n1ttEW_emptyState",
|
|
372
|
+
"fileDir": "n1ttEW_fileDir",
|
|
373
|
+
"fileItem": "n1ttEW_fileItem",
|
|
374
|
+
"fileItemActions": "n1ttEW_fileItemActions",
|
|
375
|
+
"fileLeft": "n1ttEW_fileLeft",
|
|
376
|
+
"fileList": "n1ttEW_fileList",
|
|
377
|
+
"fileMiniBtn": "n1ttEW_fileMiniBtn",
|
|
378
|
+
"fileName": "n1ttEW_fileName",
|
|
379
|
+
"footerStats": "n1ttEW_footerStats",
|
|
380
|
+
"footerSyncStatus": "n1ttEW_footerSyncStatus",
|
|
381
|
+
"graphOverlaySvg": "n1ttEW_graphOverlaySvg",
|
|
382
|
+
"graphSvg": "n1ttEW_graphSvg",
|
|
383
|
+
"header": "n1ttEW_header",
|
|
384
|
+
"headerActions": "n1ttEW_headerActions",
|
|
385
|
+
"iconButton": "n1ttEW_iconButton",
|
|
386
|
+
"loadMoreLink": "n1ttEW_loadMoreLink",
|
|
387
|
+
"locateGlowRing": "n1ttEW_locateGlowRing",
|
|
388
|
+
"mainlineToggleBtn": "n1ttEW_mainlineToggleBtn",
|
|
389
|
+
"mainlineToggleBtnActive": "n1ttEW_mainlineToggleBtnActive",
|
|
390
|
+
"mainlineToggleGroup": "n1ttEW_mainlineToggleGroup",
|
|
391
|
+
"numstat": "n1ttEW_numstat",
|
|
392
|
+
"pulseRing": "n1ttEW_pulseRing",
|
|
393
|
+
"refBadge": "n1ttEW_refBadge",
|
|
394
|
+
"refBranch": "n1ttEW_refBranch",
|
|
395
|
+
"refHead": "n1ttEW_refHead",
|
|
396
|
+
"refRemote": "n1ttEW_refRemote",
|
|
397
|
+
"refTag": "n1ttEW_refTag",
|
|
398
|
+
"root": "n1ttEW_root",
|
|
399
|
+
"rowGlow": "n1ttEW_rowGlow",
|
|
400
|
+
"section": "n1ttEW_section",
|
|
401
|
+
"sectionActions": "n1ttEW_sectionActions",
|
|
402
|
+
"sectionHeader": "n1ttEW_sectionHeader",
|
|
403
|
+
"sectionTitle": "n1ttEW_sectionTitle",
|
|
404
|
+
"shaCol": "n1ttEW_shaCol",
|
|
405
|
+
"spin": "n1ttEW_spin",
|
|
406
|
+
"spinning": "n1ttEW_spinning",
|
|
407
|
+
"statusA": "n1ttEW_statusA",
|
|
408
|
+
"statusAheadBehind": "n1ttEW_statusAheadBehind",
|
|
409
|
+
"statusBadge": "n1ttEW_statusBadge",
|
|
410
|
+
"statusD": "n1ttEW_statusD",
|
|
411
|
+
"statusM": "n1ttEW_statusM",
|
|
412
|
+
"statusU": "n1ttEW_statusU",
|
|
413
|
+
"subjectCol": "n1ttEW_subjectCol",
|
|
414
|
+
"syncDot": "n1ttEW_syncDot",
|
|
415
|
+
"tab": "n1ttEW_tab",
|
|
416
|
+
"tabActive": "n1ttEW_tabActive",
|
|
417
|
+
"tabCount": "n1ttEW_tabCount",
|
|
418
|
+
"tablePane": "n1ttEW_tablePane",
|
|
419
|
+
"tabs": "n1ttEW_tabs",
|
|
420
|
+
"tagActions": "n1ttEW_tagActions",
|
|
421
|
+
"tagAnnotatedBadge": "n1ttEW_tagAnnotatedBadge",
|
|
422
|
+
"tagAuthor": "n1ttEW_tagAuthor",
|
|
423
|
+
"tagCard": "n1ttEW_tagCard",
|
|
424
|
+
"tagCardHeader": "n1ttEW_tagCardHeader",
|
|
425
|
+
"tagForm": "n1ttEW_tagForm",
|
|
426
|
+
"tagFormActions": "n1ttEW_tagFormActions",
|
|
427
|
+
"tagFormTitle": "n1ttEW_tagFormTitle",
|
|
428
|
+
"tagList": "n1ttEW_tagList",
|
|
429
|
+
"tagLocateBtn": "n1ttEW_tagLocateBtn",
|
|
430
|
+
"tagMessage": "n1ttEW_tagMessage",
|
|
431
|
+
"tagMetaFooter": "n1ttEW_tagMetaFooter",
|
|
432
|
+
"tagName": "n1ttEW_tagName",
|
|
433
|
+
"tagShaPill": "n1ttEW_tagShaPill",
|
|
434
|
+
"tagTitleRow": "n1ttEW_tagTitleRow",
|
|
435
|
+
"timeCol": "n1ttEW_timeCol",
|
|
436
|
+
"treeActionBtn": "n1ttEW_treeActionBtn",
|
|
437
|
+
"treeAuthor": "n1ttEW_treeAuthor",
|
|
438
|
+
"treeBody": "n1ttEW_treeBody",
|
|
439
|
+
"treeContainer": "n1ttEW_treeContainer",
|
|
440
|
+
"treeFilterRow": "n1ttEW_treeFilterRow",
|
|
441
|
+
"treeHash": "n1ttEW_treeHash",
|
|
442
|
+
"treeRow": "n1ttEW_treeRow",
|
|
443
|
+
"treeRowActions": "n1ttEW_treeRowActions",
|
|
444
|
+
"treeRowGrid": "n1ttEW_treeRowGrid",
|
|
445
|
+
"treeRowGridSelected": "n1ttEW_treeRowGridSelected",
|
|
446
|
+
"treeRowHighlighted": "n1ttEW_treeRowHighlighted",
|
|
447
|
+
"treeRowSelected": "n1ttEW_treeRowSelected",
|
|
448
|
+
"treeSearchInput": "n1ttEW_treeSearchInput",
|
|
449
|
+
"treeStatusFooter": "n1ttEW_treeStatusFooter",
|
|
450
|
+
"treeSubject": "n1ttEW_treeSubject",
|
|
451
|
+
"treeTableHeader": "n1ttEW_treeTableHeader",
|
|
452
|
+
"treeTime": "n1ttEW_treeTime",
|
|
453
|
+
"typeBadge": "n1ttEW_typeBadge",
|
|
454
|
+
"typeChore": "n1ttEW_typeChore",
|
|
455
|
+
"typeDocs": "n1ttEW_typeDocs",
|
|
456
|
+
"typeFeat": "n1ttEW_typeFeat",
|
|
457
|
+
"typeFix": "n1ttEW_typeFix",
|
|
458
|
+
"typeMerge": "n1ttEW_typeMerge",
|
|
459
|
+
"typeRefactor": "n1ttEW_typeRefactor",
|
|
460
|
+
"typeRelease": "n1ttEW_typeRelease",
|
|
461
|
+
"typeRevert": "n1ttEW_typeRevert",
|
|
462
|
+
"typeStyle": "n1ttEW_typeStyle",
|
|
463
|
+
"typeTest": "n1ttEW_typeTest",
|
|
464
|
+
"workstationLayout": "n1ttEW_workstationLayout"
|
|
465
|
+
};
|
|
466
|
+
//#endregion
|
|
467
|
+
//#region lib/types/client/GitBody.js
|
|
468
|
+
/**
|
|
469
|
+
* IntelliJ IDEA-Grade Git Tool Window Component.
|
|
470
|
+
* Supports DAG commit topology graph visualization, working tree staging, commit console,
|
|
471
|
+
* branch switcher, and unified diff inspector.
|
|
472
|
+
*/
|
|
473
|
+
function getTypeBadgeClass(type) {
|
|
474
|
+
switch (type) {
|
|
475
|
+
case "feat": return GitBody_module_css_default.typeFeat ?? "";
|
|
476
|
+
case "fix": return GitBody_module_css_default.typeFix ?? "";
|
|
477
|
+
case "style": return GitBody_module_css_default.typeStyle ?? "";
|
|
478
|
+
case "refactor": return GitBody_module_css_default.typeRefactor ?? "";
|
|
479
|
+
case "release": return GitBody_module_css_default.typeRelease ?? "";
|
|
480
|
+
case "merge": return GitBody_module_css_default.typeMerge ?? "";
|
|
481
|
+
case "test": return GitBody_module_css_default.typeTest ?? "";
|
|
482
|
+
case "docs": return GitBody_module_css_default.typeDocs ?? "";
|
|
483
|
+
case "revert": return GitBody_module_css_default.typeRevert ?? "";
|
|
484
|
+
default: return GitBody_module_css_default.typeChore ?? "";
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Render color-coded unified diff lines.
|
|
489
|
+
*/
|
|
490
|
+
function DiffViewer({ diffText }) {
|
|
491
|
+
if (!diffText.trim()) return (0, react_jsx_runtime.jsx)("div", {
|
|
492
|
+
className: GitBody_module_css_default.diffViewer,
|
|
493
|
+
children: "无代码内容变动"
|
|
494
|
+
});
|
|
495
|
+
const lines = diffText.split("\n");
|
|
496
|
+
return (0, react_jsx_runtime.jsx)("div", {
|
|
497
|
+
className: GitBody_module_css_default.diffViewer,
|
|
498
|
+
children: lines.map((line, idx) => {
|
|
499
|
+
let lineClass = GitBody_module_css_default.diffLine;
|
|
500
|
+
if (line.startsWith("+") && !line.startsWith("+++")) lineClass = `${GitBody_module_css_default.diffLine} ${GitBody_module_css_default.diffAdd}`;
|
|
501
|
+
else if (line.startsWith("-") && !line.startsWith("---")) lineClass = `${GitBody_module_css_default.diffLine} ${GitBody_module_css_default.diffDel}`;
|
|
502
|
+
else if (line.startsWith("@@")) lineClass = `${GitBody_module_css_default.diffLine} ${GitBody_module_css_default.diffHunk}`;
|
|
503
|
+
return (0, react_jsx_runtime.jsx)("div", {
|
|
504
|
+
className: lineClass,
|
|
505
|
+
children: line || " "
|
|
506
|
+
}, idx);
|
|
507
|
+
})
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Main Git Body Component.
|
|
512
|
+
*/
|
|
513
|
+
const GitBody = (0, react.memo)(function GitBody(props) {
|
|
514
|
+
const { t, sessionId, getStatus, getLog, getCommitDetails, getDiff, getBranches, getTags, createTag, deleteTag, checkout, stage, unstage, discard, commit, fetch: fetchGit, pull, push } = props;
|
|
515
|
+
const [activeTab, setActiveTab] = (0, react.useState)("changes");
|
|
516
|
+
const [loading, setLoading] = (0, react.useState)(false);
|
|
517
|
+
const [status, setStatus] = (0, react.useState)(null);
|
|
518
|
+
const [commits, setCommits] = (0, react.useState)([]);
|
|
519
|
+
const [branches, setBranches] = (0, react.useState)(null);
|
|
520
|
+
const [tags, setTags] = (0, react.useState)([]);
|
|
521
|
+
const [commitMessage, setCommitMessage] = (0, react.useState)("");
|
|
522
|
+
const [committing, setCommitting] = (0, react.useState)(false);
|
|
523
|
+
const [selectedFileDiff, setSelectedFileDiff] = (0, react.useState)(null);
|
|
524
|
+
const [selectedCommitHash, setSelectedCommitHash] = (0, react.useState)(null);
|
|
525
|
+
const [commitDetail, setCommitDetail] = (0, react.useState)(null);
|
|
526
|
+
const [highlightedCommitHash, setHighlightedCommitHash] = (0, react.useState)(null);
|
|
527
|
+
const [locatedNotice, setLocatedNotice] = (0, react.useState)(null);
|
|
528
|
+
const [treeSearch, setTreeSearch] = (0, react.useState)("");
|
|
529
|
+
const [filterMode, setFilterMode] = (0, react.useState)("all");
|
|
530
|
+
const [branchFilter, setBranchFilter] = (0, react.useState)("");
|
|
531
|
+
const [newBranchName, setNewBranchName] = (0, react.useState)("");
|
|
532
|
+
const [creatingBranch, setCreatingBranch] = (0, react.useState)(false);
|
|
533
|
+
const [tagFilter, setTagFilter] = (0, react.useState)("");
|
|
534
|
+
const [creatingTag, setCreatingTag] = (0, react.useState)(false);
|
|
535
|
+
const [newTagName, setNewTagName] = (0, react.useState)("");
|
|
536
|
+
const [newTagCommit, setNewTagCommit] = (0, react.useState)("");
|
|
537
|
+
const [newTagMessage, setNewTagMessage] = (0, react.useState)("");
|
|
538
|
+
const refresh = (0, react.useCallback)(async () => {
|
|
539
|
+
setLoading(true);
|
|
540
|
+
try {
|
|
541
|
+
const [statusRes, logRes, branchRes, tagRes] = await Promise.all([
|
|
542
|
+
getStatus(sessionId).catch(() => null),
|
|
543
|
+
getLog(sessionId, 50).catch(() => []),
|
|
544
|
+
getBranches(sessionId).catch(() => null),
|
|
545
|
+
getTags(sessionId).catch(() => [])
|
|
546
|
+
]);
|
|
547
|
+
if (statusRes) setStatus(statusRes);
|
|
548
|
+
setCommits(logRes);
|
|
549
|
+
if (branchRes) setBranches(branchRes);
|
|
550
|
+
setTags(tagRes);
|
|
551
|
+
} finally {
|
|
552
|
+
setLoading(false);
|
|
553
|
+
}
|
|
554
|
+
}, [
|
|
555
|
+
getBranches,
|
|
556
|
+
getLog,
|
|
557
|
+
getStatus,
|
|
558
|
+
getTags,
|
|
559
|
+
sessionId
|
|
560
|
+
]);
|
|
561
|
+
(0, react.useEffect)(() => {
|
|
562
|
+
refresh();
|
|
563
|
+
}, [refresh]);
|
|
564
|
+
const handleSelectCommit = (0, react.useCallback)(async (hash) => {
|
|
565
|
+
if (selectedCommitHash === hash) {
|
|
566
|
+
setSelectedCommitHash(null);
|
|
567
|
+
setCommitDetail(null);
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
570
|
+
setSelectedCommitHash(hash);
|
|
571
|
+
try {
|
|
572
|
+
setCommitDetail(await getCommitDetails(sessionId, hash) ?? null);
|
|
573
|
+
} catch {
|
|
574
|
+
setCommitDetail(null);
|
|
575
|
+
}
|
|
576
|
+
}, [
|
|
577
|
+
getCommitDetails,
|
|
578
|
+
selectedCommitHash,
|
|
579
|
+
sessionId
|
|
580
|
+
]);
|
|
581
|
+
const handleViewDiff = (0, react.useCallback)(async (path, staged, commitHash) => {
|
|
582
|
+
try {
|
|
583
|
+
setSelectedFileDiff({
|
|
584
|
+
path,
|
|
585
|
+
staged,
|
|
586
|
+
diff: (await getDiff(sessionId, {
|
|
587
|
+
filePath: path,
|
|
588
|
+
staged,
|
|
589
|
+
...commitHash !== void 0 ? { commit: commitHash } : {}
|
|
590
|
+
})).rawDiff
|
|
591
|
+
});
|
|
592
|
+
} catch {
|
|
593
|
+
setSelectedFileDiff(null);
|
|
594
|
+
}
|
|
595
|
+
}, [getDiff, sessionId]);
|
|
596
|
+
const handleStage = (0, react.useCallback)(async (paths) => {
|
|
597
|
+
await stage(sessionId, paths);
|
|
598
|
+
await refresh();
|
|
599
|
+
}, [
|
|
600
|
+
refresh,
|
|
601
|
+
sessionId,
|
|
602
|
+
stage
|
|
603
|
+
]);
|
|
604
|
+
const handleUnstage = (0, react.useCallback)(async (paths) => {
|
|
605
|
+
await unstage(sessionId, paths);
|
|
606
|
+
await refresh();
|
|
607
|
+
}, [
|
|
608
|
+
refresh,
|
|
609
|
+
sessionId,
|
|
610
|
+
unstage
|
|
611
|
+
]);
|
|
612
|
+
const handleDiscard = (0, react.useCallback)(async (paths) => {
|
|
613
|
+
if (confirm(`确认放弃对 ${paths.length} 个文件的所有更改吗?此操作无法撤销。`)) {
|
|
614
|
+
await discard(sessionId, paths);
|
|
615
|
+
await refresh();
|
|
616
|
+
}
|
|
617
|
+
}, [
|
|
618
|
+
discard,
|
|
619
|
+
refresh,
|
|
620
|
+
sessionId
|
|
621
|
+
]);
|
|
622
|
+
const handleCommit = (0, react.useCallback)(async (andPush = false) => {
|
|
623
|
+
const trimmed = commitMessage.trim();
|
|
624
|
+
if (!trimmed) {
|
|
625
|
+
alert(t("commit.emptyWarning"));
|
|
626
|
+
return;
|
|
627
|
+
}
|
|
628
|
+
setCommitting(true);
|
|
629
|
+
try {
|
|
630
|
+
const res = await commit(sessionId, trimmed);
|
|
631
|
+
if (res.success) {
|
|
632
|
+
setCommitMessage("");
|
|
633
|
+
if (andPush) await push(sessionId);
|
|
634
|
+
await refresh();
|
|
635
|
+
} else alert(res.message || "提交失败");
|
|
636
|
+
} finally {
|
|
637
|
+
setCommitting(false);
|
|
638
|
+
}
|
|
639
|
+
}, [
|
|
640
|
+
commit,
|
|
641
|
+
commitMessage,
|
|
642
|
+
push,
|
|
643
|
+
refresh,
|
|
644
|
+
sessionId,
|
|
645
|
+
t
|
|
646
|
+
]);
|
|
647
|
+
const handleCommitKeyDown = (0, react.useCallback)((e) => {
|
|
648
|
+
if ((e.ctrlKey || e.metaKey) && e.key === "Enter") {
|
|
649
|
+
e.preventDefault();
|
|
650
|
+
handleCommit(false);
|
|
651
|
+
}
|
|
652
|
+
}, [handleCommit]);
|
|
653
|
+
const handleCheckoutBranch = (0, react.useCallback)(async (bName, create = false) => {
|
|
654
|
+
const res = await checkout(sessionId, bName, create);
|
|
655
|
+
if (res.success) {
|
|
656
|
+
setCreatingBranch(false);
|
|
657
|
+
setNewBranchName("");
|
|
658
|
+
await refresh();
|
|
659
|
+
} else alert(res.message || "检出失败");
|
|
660
|
+
}, [
|
|
661
|
+
checkout,
|
|
662
|
+
refresh,
|
|
663
|
+
sessionId
|
|
664
|
+
]);
|
|
665
|
+
const handleLocateCommit = (0, react.useCallback)(async (commitHash, tagName) => {
|
|
666
|
+
setActiveTab("tree");
|
|
667
|
+
let found = commits.find((c) => c.hash.startsWith(commitHash) || commitHash.startsWith(c.hash));
|
|
668
|
+
if (!found) try {
|
|
669
|
+
const deepLogs = await getLog(sessionId, 200);
|
|
670
|
+
setCommits(deepLogs);
|
|
671
|
+
found = deepLogs.find((c) => c.hash.startsWith(commitHash) || commitHash.startsWith(c.hash));
|
|
672
|
+
} catch {}
|
|
673
|
+
if (found) {
|
|
674
|
+
setSelectedCommitHash(found.hash);
|
|
675
|
+
setHighlightedCommitHash(found.hash);
|
|
676
|
+
if (tagName) {
|
|
677
|
+
setLocatedNotice(t("tag.locatedNotice", { name: tagName }));
|
|
678
|
+
setTimeout(() => {
|
|
679
|
+
setLocatedNotice(null);
|
|
680
|
+
}, 3e3);
|
|
681
|
+
}
|
|
682
|
+
handleSelectCommit(found.hash);
|
|
683
|
+
setTimeout(() => {
|
|
684
|
+
document.getElementById(`git-commit-${found.hash}`)?.scrollIntoView({
|
|
685
|
+
behavior: "smooth",
|
|
686
|
+
block: "center"
|
|
687
|
+
});
|
|
688
|
+
}, 50);
|
|
689
|
+
setTimeout(() => {
|
|
690
|
+
setHighlightedCommitHash(null);
|
|
691
|
+
}, 3500);
|
|
692
|
+
}
|
|
693
|
+
}, [
|
|
694
|
+
commits,
|
|
695
|
+
getLog,
|
|
696
|
+
handleSelectCommit,
|
|
697
|
+
sessionId,
|
|
698
|
+
t
|
|
699
|
+
]);
|
|
700
|
+
const handleCreateTag = (0, react.useCallback)(async () => {
|
|
701
|
+
const name = newTagName.trim();
|
|
702
|
+
if (!name) {
|
|
703
|
+
alert("请输入标签名称");
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
const res = await createTag(sessionId, name, newTagCommit.trim() || void 0, newTagMessage.trim() || void 0);
|
|
707
|
+
if (res.success) {
|
|
708
|
+
setCreatingTag(false);
|
|
709
|
+
setNewTagName("");
|
|
710
|
+
setNewTagCommit("");
|
|
711
|
+
setNewTagMessage("");
|
|
712
|
+
await refresh();
|
|
713
|
+
} else alert(res.message || "创建标签失败");
|
|
714
|
+
}, [
|
|
715
|
+
createTag,
|
|
716
|
+
newTagCommit,
|
|
717
|
+
newTagMessage,
|
|
718
|
+
newTagName,
|
|
719
|
+
refresh,
|
|
720
|
+
sessionId
|
|
721
|
+
]);
|
|
722
|
+
const handleDeleteTag = (0, react.useCallback)(async (tagName) => {
|
|
723
|
+
if (confirm(t("tag.deleteConfirm", { name: tagName }))) {
|
|
724
|
+
const res = await deleteTag(sessionId, tagName);
|
|
725
|
+
if (res.success) await refresh();
|
|
726
|
+
else alert(res.message || "删除标签失败");
|
|
727
|
+
}
|
|
728
|
+
}, [
|
|
729
|
+
deleteTag,
|
|
730
|
+
refresh,
|
|
731
|
+
sessionId,
|
|
732
|
+
t
|
|
733
|
+
]);
|
|
734
|
+
const filteredLocalBranches = (0, react.useMemo)(() => {
|
|
735
|
+
if (!branches?.local) return [];
|
|
736
|
+
const q = branchFilter.trim().toLowerCase();
|
|
737
|
+
return q ? branches.local.filter((b) => b.name.toLowerCase().includes(q)) : branches.local;
|
|
738
|
+
}, [branches?.local, branchFilter]);
|
|
739
|
+
const filteredRemoteBranches = (0, react.useMemo)(() => {
|
|
740
|
+
if (!branches?.remote) return [];
|
|
741
|
+
const q = branchFilter.trim().toLowerCase();
|
|
742
|
+
return q ? branches.remote.filter((b) => b.name.toLowerCase().includes(q)) : branches.remote;
|
|
743
|
+
}, [branches?.remote, branchFilter]);
|
|
744
|
+
const filteredTags = (0, react.useMemo)(() => {
|
|
745
|
+
const q = tagFilter.trim().toLowerCase();
|
|
746
|
+
if (!q) return tags;
|
|
747
|
+
return tags.filter((item) => item.name.toLowerCase().includes(q) || item.shortHash.toLowerCase().includes(q) || item.commitHash.toLowerCase().includes(q) || item.message.toLowerCase().includes(q) || item.author.toLowerCase().includes(q));
|
|
748
|
+
}, [tags, tagFilter]);
|
|
749
|
+
const filteredCommits = (0, react.useMemo)(() => {
|
|
750
|
+
let list = commits;
|
|
751
|
+
if (filterMode === "mainline") list = list.filter((c) => (c.lane ?? 0) === 0);
|
|
752
|
+
const q = treeSearch.trim().toLowerCase();
|
|
753
|
+
if (q) list = list.filter((c) => c.subject.toLowerCase().includes(q) || c.hash.toLowerCase().includes(q) || c.shortHash.toLowerCase().includes(q) || c.author.toLowerCase().includes(q) || c.refs && c.refs.some((r) => r.toLowerCase().includes(q)));
|
|
754
|
+
return list;
|
|
755
|
+
}, [
|
|
756
|
+
commits,
|
|
757
|
+
filterMode,
|
|
758
|
+
treeSearch
|
|
759
|
+
]);
|
|
760
|
+
const handleLoadMore = (0, react.useCallback)(async () => {
|
|
761
|
+
setLoading(true);
|
|
762
|
+
try {
|
|
763
|
+
setCommits(await getLog(sessionId, commits.length + 50));
|
|
764
|
+
} finally {
|
|
765
|
+
setLoading(false);
|
|
766
|
+
}
|
|
767
|
+
}, [
|
|
768
|
+
commits.length,
|
|
769
|
+
getLog,
|
|
770
|
+
sessionId
|
|
771
|
+
]);
|
|
772
|
+
const dagGraph = (0, react.useMemo)(() => computeDagGraph(filteredCommits), [filteredCommits]);
|
|
773
|
+
const graphColWidth = dagGraph.graphWidth;
|
|
774
|
+
if (!status || !status.isRepo) return (0, react_jsx_runtime.jsx)("div", {
|
|
775
|
+
className: GitBody_module_css_default.root,
|
|
776
|
+
children: (0, react_jsx_runtime.jsxs)("div", {
|
|
777
|
+
className: GitBody_module_css_default.emptyState,
|
|
778
|
+
children: [(0, react_jsx_runtime.jsx)("svg", {
|
|
779
|
+
viewBox: "0 0 16 16",
|
|
780
|
+
fill: "currentColor",
|
|
781
|
+
children: (0, react_jsx_runtime.jsx)("path", { d: "M2 2.5A2.5 2.5 0 0 1 4.5 0h8.75a.75.75 0 0 1 .75.75v12.5a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1 0-1.5h1.75v-2h-8a1 1 0 0 0-.714 1.7.75.75 0 1 1-1.072 1.05A2.495 2.495 0 0 1 2 11.5v-9zm10.5-1h-8a1 1 0 0 0-1 1v6.708A2.486 2.486 0 0 1 4.5 9h8V1.5z" })
|
|
782
|
+
}), (0, react_jsx_runtime.jsx)("div", { children: t("status.notRepo") })]
|
|
783
|
+
})
|
|
784
|
+
});
|
|
785
|
+
const stagedCount = status.staged.length;
|
|
786
|
+
const unstagedCount = status.unstaged.length;
|
|
787
|
+
const untrackedCount = status.untracked.length;
|
|
788
|
+
const totalChanges = status.totalChanges;
|
|
789
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
790
|
+
className: GitBody_module_css_default.root,
|
|
791
|
+
children: [
|
|
792
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
793
|
+
className: GitBody_module_css_default.header,
|
|
794
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
795
|
+
className: GitBody_module_css_default.branchInfo,
|
|
796
|
+
children: [(0, react_jsx_runtime.jsxs)("span", {
|
|
797
|
+
className: GitBody_module_css_default.branchBadge,
|
|
798
|
+
title: `当前分支: ${status.branch}`,
|
|
799
|
+
children: [(0, react_jsx_runtime.jsx)("svg", {
|
|
800
|
+
className: GitBody_module_css_default.branchIcon,
|
|
801
|
+
width: "12",
|
|
802
|
+
height: "12",
|
|
803
|
+
viewBox: "0 0 16 16",
|
|
804
|
+
fill: "currentColor",
|
|
805
|
+
children: (0, react_jsx_runtime.jsx)("path", { d: "M11.75 2.5a1.75 1.75 0 1 0-2.45 1.606V6.5a1.5 1.5 0 0 1-1.5 1.5H5.8A2.75 2.75 0 0 0 3.5 6.25V4.106a1.75 1.75 0 1 0-1.5 0v7.788a1.75 1.75 0 1 0 1.5 0V8.25A1.25 1.25 0 0 1 4.75 7h3a3 3 0 0 0 3-3V4.106a1.75 1.75 0 0 0 1-1.606z" })
|
|
806
|
+
}), status.branch || "HEAD"]
|
|
807
|
+
}), (status.ahead > 0 || status.behind > 0) && (0, react_jsx_runtime.jsxs)("div", {
|
|
808
|
+
className: GitBody_module_css_default.statusAheadBehind,
|
|
809
|
+
children: [status.ahead > 0 && (0, react_jsx_runtime.jsxs)("span", {
|
|
810
|
+
className: GitBody_module_css_default.aheadText,
|
|
811
|
+
children: ["↑", status.ahead]
|
|
812
|
+
}), status.behind > 0 && (0, react_jsx_runtime.jsxs)("span", {
|
|
813
|
+
className: GitBody_module_css_default.behindText,
|
|
814
|
+
children: ["↓", status.behind]
|
|
815
|
+
})]
|
|
816
|
+
})]
|
|
817
|
+
}), (0, react_jsx_runtime.jsxs)("div", {
|
|
818
|
+
className: GitBody_module_css_default.headerActions,
|
|
819
|
+
children: [
|
|
820
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
821
|
+
type: "button",
|
|
822
|
+
className: GitBody_module_css_default.iconButton,
|
|
823
|
+
title: t("actions.fetch"),
|
|
824
|
+
onClick: () => {
|
|
825
|
+
fetchGit(sessionId).then(() => refresh());
|
|
826
|
+
},
|
|
827
|
+
children: (0, react_jsx_runtime.jsx)("svg", {
|
|
828
|
+
width: "14",
|
|
829
|
+
height: "14",
|
|
830
|
+
viewBox: "0 0 16 16",
|
|
831
|
+
fill: "currentColor",
|
|
832
|
+
children: (0, react_jsx_runtime.jsx)("path", { d: "M1.75 3a.75.75 0 0 0 0 1.5h8.5a3.25 3.25 0 0 1 3.25 3.25v2.44l1.72-1.72a.75.75 0 1 1 1.06 1.06l-3 3a.75.75 0 0 1-1.06 0l-3-3a.75.75 0 1 1 1.06-1.06l1.72 1.72V7.75A1.75 1.75 0 0 0 10.25 6H1.75a.75.75 0 0 0 0-1.5z" })
|
|
833
|
+
})
|
|
834
|
+
}),
|
|
835
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
836
|
+
type: "button",
|
|
837
|
+
className: GitBody_module_css_default.iconButton,
|
|
838
|
+
title: "拉取 (Pull)",
|
|
839
|
+
onClick: () => {
|
|
840
|
+
pull(sessionId).then(() => refresh());
|
|
841
|
+
},
|
|
842
|
+
children: (0, react_jsx_runtime.jsx)("svg", {
|
|
843
|
+
width: "14",
|
|
844
|
+
height: "14",
|
|
845
|
+
viewBox: "0 0 16 16",
|
|
846
|
+
fill: "currentColor",
|
|
847
|
+
children: (0, react_jsx_runtime.jsx)("path", { d: "M13.03 8.22a.75.75 0 0 1 0 1.06l-4.5 4.5a.75.75 0 0 1-1.06 0l-4.5-4.5a.75.75 0 0 1 1.06-1.06L7.5 11.69V2.75a.75.75 0 0 1 1.5 0v8.94l3.47-3.47a.75.75 0 0 1 1.06 0z" })
|
|
848
|
+
})
|
|
849
|
+
}),
|
|
850
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
851
|
+
type: "button",
|
|
852
|
+
className: GitBody_module_css_default.iconButton,
|
|
853
|
+
title: "推送 (Push)",
|
|
854
|
+
onClick: () => {
|
|
855
|
+
push(sessionId).then(() => refresh());
|
|
856
|
+
},
|
|
857
|
+
children: (0, react_jsx_runtime.jsx)("svg", {
|
|
858
|
+
width: "14",
|
|
859
|
+
height: "14",
|
|
860
|
+
viewBox: "0 0 16 16",
|
|
861
|
+
fill: "currentColor",
|
|
862
|
+
children: (0, react_jsx_runtime.jsx)("path", { d: "M2.97 7.78a.75.75 0 0 1 0-1.06l4.5-4.5a.75.75 0 0 1 1.06 0l4.5 4.5a.75.75 0 1 1-1.06 1.06L8.5 4.31v8.94a.75.75 0 0 1-1.5 0V4.31L3.53 7.78a.75.75 0 0 1-1.06 0z" })
|
|
863
|
+
})
|
|
864
|
+
}),
|
|
865
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
866
|
+
type: "button",
|
|
867
|
+
className: `${GitBody_module_css_default.iconButton} ${loading ? GitBody_module_css_default.spinning : ""}`,
|
|
868
|
+
title: "刷新",
|
|
869
|
+
onClick: () => {
|
|
870
|
+
refresh();
|
|
871
|
+
},
|
|
872
|
+
children: (0, react_jsx_runtime.jsx)("svg", {
|
|
873
|
+
width: "14",
|
|
874
|
+
height: "14",
|
|
875
|
+
viewBox: "0 0 16 16",
|
|
876
|
+
fill: "currentColor",
|
|
877
|
+
children: (0, react_jsx_runtime.jsx)("path", { d: "M1.705 8.005a.75.75 0 0 1 .834.656 5.5 5.5 0 0 0 9.592 2.97l-1.204-1.204a.25.25 0 0 1 .177-.427h3.646a.25.25 0 0 1 .25.25v3.646a.25.25 0 0 1-.427.177l-1.38-1.38A7.002 7.002 0 0 1 1.05 8.84a.75.75 0 0 1 .655-.835zm12.59-1.01a.75.75 0 0 1-.834-.656 5.5 5.5 0 0 0-9.592-2.97l1.204 1.204a.25.25 0 0 1-.177.427H1.25a.25.25 0 0 1-.25-.25V1.104a.25.25 0 0 1 .427-.177l1.38 1.38A7.002 7.002 0 0 1 14.95 7.16a.75.75 0 0 1-.655.835z" })
|
|
878
|
+
})
|
|
879
|
+
})
|
|
880
|
+
]
|
|
881
|
+
})]
|
|
882
|
+
}),
|
|
883
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
884
|
+
className: GitBody_module_css_default.tabs,
|
|
885
|
+
children: [
|
|
886
|
+
(0, react_jsx_runtime.jsxs)("button", {
|
|
887
|
+
type: "button",
|
|
888
|
+
className: `${GitBody_module_css_default.tab} ${activeTab === "changes" ? GitBody_module_css_default.tabActive : ""}`,
|
|
889
|
+
onClick: () => {
|
|
890
|
+
setActiveTab("changes");
|
|
891
|
+
},
|
|
892
|
+
children: [t("tabs.changes"), totalChanges > 0 && (0, react_jsx_runtime.jsx)("span", {
|
|
893
|
+
className: GitBody_module_css_default.tabCount,
|
|
894
|
+
children: totalChanges
|
|
895
|
+
})]
|
|
896
|
+
}),
|
|
897
|
+
(0, react_jsx_runtime.jsxs)("button", {
|
|
898
|
+
type: "button",
|
|
899
|
+
className: `${GitBody_module_css_default.tab} ${activeTab === "tree" ? GitBody_module_css_default.tabActive : ""}`,
|
|
900
|
+
onClick: () => {
|
|
901
|
+
setActiveTab("tree");
|
|
902
|
+
},
|
|
903
|
+
children: [t("tabs.tree"), (0, react_jsx_runtime.jsx)("span", {
|
|
904
|
+
className: GitBody_module_css_default.tabCount,
|
|
905
|
+
children: commits.length
|
|
906
|
+
})]
|
|
907
|
+
}),
|
|
908
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
909
|
+
type: "button",
|
|
910
|
+
className: `${GitBody_module_css_default.tab} ${activeTab === "branches" ? GitBody_module_css_default.tabActive : ""}`,
|
|
911
|
+
onClick: () => {
|
|
912
|
+
setActiveTab("branches");
|
|
913
|
+
},
|
|
914
|
+
children: t("tabs.branches")
|
|
915
|
+
}),
|
|
916
|
+
(0, react_jsx_runtime.jsxs)("button", {
|
|
917
|
+
type: "button",
|
|
918
|
+
className: `${GitBody_module_css_default.tab} ${activeTab === "tags" ? GitBody_module_css_default.tabActive : ""}`,
|
|
919
|
+
onClick: () => {
|
|
920
|
+
setActiveTab("tags");
|
|
921
|
+
},
|
|
922
|
+
children: [t("tabs.tags"), tags.length > 0 && (0, react_jsx_runtime.jsx)("span", {
|
|
923
|
+
className: GitBody_module_css_default.tabCount,
|
|
924
|
+
children: tags.length
|
|
925
|
+
})]
|
|
926
|
+
})
|
|
927
|
+
]
|
|
928
|
+
}),
|
|
929
|
+
locatedNotice && (0, react_jsx_runtime.jsxs)("div", {
|
|
930
|
+
style: {
|
|
931
|
+
padding: "6px 12px",
|
|
932
|
+
background: "color-mix(in srgb, var(--dsw-alias-state-business-primary) 18%, transparent)",
|
|
933
|
+
color: "var(--dsw-alias-state-business-primary)",
|
|
934
|
+
fontSize: "11px",
|
|
935
|
+
fontWeight: 600,
|
|
936
|
+
display: "flex",
|
|
937
|
+
alignItems: "center",
|
|
938
|
+
gap: "6px",
|
|
939
|
+
borderBottom: "0.5px solid var(--dsw-alias-border-l2)"
|
|
940
|
+
},
|
|
941
|
+
children: [(0, react_jsx_runtime.jsx)("span", { children: "🎯" }), (0, react_jsx_runtime.jsx)("span", { children: locatedNotice })]
|
|
942
|
+
}),
|
|
943
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
944
|
+
className: GitBody_module_css_default.content,
|
|
945
|
+
children: [
|
|
946
|
+
activeTab === "changes" && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [totalChanges === 0 ? (0, react_jsx_runtime.jsxs)("div", {
|
|
947
|
+
className: GitBody_module_css_default.emptyState,
|
|
948
|
+
children: [(0, react_jsx_runtime.jsx)("svg", {
|
|
949
|
+
viewBox: "0 0 16 16",
|
|
950
|
+
fill: "currentColor",
|
|
951
|
+
children: (0, react_jsx_runtime.jsx)("path", { d: "M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0z" })
|
|
952
|
+
}), (0, react_jsx_runtime.jsx)("div", { children: t("status.clean") })]
|
|
953
|
+
}) : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
954
|
+
stagedCount > 0 && (0, react_jsx_runtime.jsxs)("div", {
|
|
955
|
+
className: GitBody_module_css_default.section,
|
|
956
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
957
|
+
className: GitBody_module_css_default.sectionHeader,
|
|
958
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
959
|
+
className: GitBody_module_css_default.sectionTitle,
|
|
960
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
961
|
+
className: `${GitBody_module_css_default.statusBadge} ${GitBody_module_css_default.statusA}`,
|
|
962
|
+
children: "✓"
|
|
963
|
+
}), (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
964
|
+
t("status.staged"),
|
|
965
|
+
" (",
|
|
966
|
+
stagedCount,
|
|
967
|
+
")"
|
|
968
|
+
] })]
|
|
969
|
+
}), (0, react_jsx_runtime.jsx)("div", {
|
|
970
|
+
className: GitBody_module_css_default.sectionActions,
|
|
971
|
+
children: (0, react_jsx_runtime.jsx)("button", {
|
|
972
|
+
type: "button",
|
|
973
|
+
className: GitBody_module_css_default.actionTextBtn,
|
|
974
|
+
title: t("actions.unstageAll"),
|
|
975
|
+
onClick: () => {
|
|
976
|
+
handleUnstage("all");
|
|
977
|
+
},
|
|
978
|
+
children: "全部取消暂存"
|
|
979
|
+
})
|
|
980
|
+
})]
|
|
981
|
+
}), (0, react_jsx_runtime.jsx)("div", {
|
|
982
|
+
className: GitBody_module_css_default.fileList,
|
|
983
|
+
children: status.staged.map((f) => (0, react_jsx_runtime.jsxs)("div", {
|
|
984
|
+
className: GitBody_module_css_default.fileItem,
|
|
985
|
+
onClick: () => {
|
|
986
|
+
handleViewDiff(f.path, true);
|
|
987
|
+
},
|
|
988
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
989
|
+
className: GitBody_module_css_default.fileLeft,
|
|
990
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
991
|
+
className: `${GitBody_module_css_default.statusBadge} ${GitBody_module_css_default.statusA}`,
|
|
992
|
+
children: f.status[0]?.toUpperCase() ?? "M"
|
|
993
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
994
|
+
className: GitBody_module_css_default.fileName,
|
|
995
|
+
children: f.path
|
|
996
|
+
})]
|
|
997
|
+
}), (0, react_jsx_runtime.jsx)("div", {
|
|
998
|
+
className: GitBody_module_css_default.fileItemActions,
|
|
999
|
+
children: (0, react_jsx_runtime.jsx)("button", {
|
|
1000
|
+
type: "button",
|
|
1001
|
+
className: GitBody_module_css_default.fileMiniBtn,
|
|
1002
|
+
title: t("actions.unstage"),
|
|
1003
|
+
onClick: (e) => {
|
|
1004
|
+
e.stopPropagation();
|
|
1005
|
+
handleUnstage([f.path]);
|
|
1006
|
+
},
|
|
1007
|
+
children: "-"
|
|
1008
|
+
})
|
|
1009
|
+
})]
|
|
1010
|
+
}, `staged-${f.path}`))
|
|
1011
|
+
})]
|
|
1012
|
+
}),
|
|
1013
|
+
unstagedCount > 0 && (0, react_jsx_runtime.jsxs)("div", {
|
|
1014
|
+
className: GitBody_module_css_default.section,
|
|
1015
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
1016
|
+
className: GitBody_module_css_default.sectionHeader,
|
|
1017
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
1018
|
+
className: GitBody_module_css_default.sectionTitle,
|
|
1019
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
1020
|
+
className: `${GitBody_module_css_default.statusBadge} ${GitBody_module_css_default.statusM}`,
|
|
1021
|
+
children: "M"
|
|
1022
|
+
}), (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
1023
|
+
t("status.unstaged"),
|
|
1024
|
+
" (",
|
|
1025
|
+
unstagedCount,
|
|
1026
|
+
")"
|
|
1027
|
+
] })]
|
|
1028
|
+
}), (0, react_jsx_runtime.jsx)("div", {
|
|
1029
|
+
className: GitBody_module_css_default.sectionActions,
|
|
1030
|
+
children: (0, react_jsx_runtime.jsx)("button", {
|
|
1031
|
+
type: "button",
|
|
1032
|
+
className: GitBody_module_css_default.actionTextBtn,
|
|
1033
|
+
title: t("actions.stageAll"),
|
|
1034
|
+
onClick: () => {
|
|
1035
|
+
handleStage("all");
|
|
1036
|
+
},
|
|
1037
|
+
children: "全部暂存"
|
|
1038
|
+
})
|
|
1039
|
+
})]
|
|
1040
|
+
}), (0, react_jsx_runtime.jsx)("div", {
|
|
1041
|
+
className: GitBody_module_css_default.fileList,
|
|
1042
|
+
children: status.unstaged.map((f) => (0, react_jsx_runtime.jsxs)("div", {
|
|
1043
|
+
className: GitBody_module_css_default.fileItem,
|
|
1044
|
+
onClick: () => {
|
|
1045
|
+
handleViewDiff(f.path, false);
|
|
1046
|
+
},
|
|
1047
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
1048
|
+
className: GitBody_module_css_default.fileLeft,
|
|
1049
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
1050
|
+
className: `${GitBody_module_css_default.statusBadge} ${GitBody_module_css_default.statusM}`,
|
|
1051
|
+
children: f.status[0]?.toUpperCase() ?? "M"
|
|
1052
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
1053
|
+
className: GitBody_module_css_default.fileName,
|
|
1054
|
+
children: f.path
|
|
1055
|
+
})]
|
|
1056
|
+
}), (0, react_jsx_runtime.jsxs)("div", {
|
|
1057
|
+
className: GitBody_module_css_default.fileItemActions,
|
|
1058
|
+
children: [(0, react_jsx_runtime.jsx)("button", {
|
|
1059
|
+
type: "button",
|
|
1060
|
+
className: GitBody_module_css_default.fileMiniBtn,
|
|
1061
|
+
title: t("actions.stage"),
|
|
1062
|
+
onClick: (e) => {
|
|
1063
|
+
e.stopPropagation();
|
|
1064
|
+
handleStage([f.path]);
|
|
1065
|
+
},
|
|
1066
|
+
children: "+"
|
|
1067
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
1068
|
+
type: "button",
|
|
1069
|
+
className: GitBody_module_css_default.fileMiniBtn,
|
|
1070
|
+
title: t("actions.discard"),
|
|
1071
|
+
onClick: (e) => {
|
|
1072
|
+
e.stopPropagation();
|
|
1073
|
+
handleDiscard([f.path]);
|
|
1074
|
+
},
|
|
1075
|
+
children: "↺"
|
|
1076
|
+
})]
|
|
1077
|
+
})]
|
|
1078
|
+
}, `unstaged-${f.path}`))
|
|
1079
|
+
})]
|
|
1080
|
+
}),
|
|
1081
|
+
untrackedCount > 0 && (0, react_jsx_runtime.jsxs)("div", {
|
|
1082
|
+
className: GitBody_module_css_default.section,
|
|
1083
|
+
children: [(0, react_jsx_runtime.jsx)("div", {
|
|
1084
|
+
className: GitBody_module_css_default.sectionHeader,
|
|
1085
|
+
children: (0, react_jsx_runtime.jsxs)("div", {
|
|
1086
|
+
className: GitBody_module_css_default.sectionTitle,
|
|
1087
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
1088
|
+
className: `${GitBody_module_css_default.statusBadge} ${GitBody_module_css_default.statusU}`,
|
|
1089
|
+
children: "?"
|
|
1090
|
+
}), (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
1091
|
+
t("status.untracked"),
|
|
1092
|
+
" (",
|
|
1093
|
+
untrackedCount,
|
|
1094
|
+
")"
|
|
1095
|
+
] })]
|
|
1096
|
+
})
|
|
1097
|
+
}), (0, react_jsx_runtime.jsx)("div", {
|
|
1098
|
+
className: GitBody_module_css_default.fileList,
|
|
1099
|
+
children: status.untracked.map((f) => (0, react_jsx_runtime.jsxs)("div", {
|
|
1100
|
+
className: GitBody_module_css_default.fileItem,
|
|
1101
|
+
onClick: () => {
|
|
1102
|
+
handleViewDiff(f.path, false);
|
|
1103
|
+
},
|
|
1104
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
1105
|
+
className: GitBody_module_css_default.fileLeft,
|
|
1106
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
1107
|
+
className: `${GitBody_module_css_default.statusBadge} ${GitBody_module_css_default.statusU}`,
|
|
1108
|
+
children: "?"
|
|
1109
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
1110
|
+
className: GitBody_module_css_default.fileName,
|
|
1111
|
+
children: f.path
|
|
1112
|
+
})]
|
|
1113
|
+
}), (0, react_jsx_runtime.jsx)("div", {
|
|
1114
|
+
className: GitBody_module_css_default.fileItemActions,
|
|
1115
|
+
children: (0, react_jsx_runtime.jsx)("button", {
|
|
1116
|
+
type: "button",
|
|
1117
|
+
className: GitBody_module_css_default.fileMiniBtn,
|
|
1118
|
+
title: t("actions.stage"),
|
|
1119
|
+
onClick: (e) => {
|
|
1120
|
+
e.stopPropagation();
|
|
1121
|
+
handleStage([f.path]);
|
|
1122
|
+
},
|
|
1123
|
+
children: "+"
|
|
1124
|
+
})
|
|
1125
|
+
})]
|
|
1126
|
+
}, `untracked-${f.path}`))
|
|
1127
|
+
})]
|
|
1128
|
+
}),
|
|
1129
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
1130
|
+
className: GitBody_module_css_default.commitBox,
|
|
1131
|
+
children: [(0, react_jsx_runtime.jsx)("textarea", {
|
|
1132
|
+
className: GitBody_module_css_default.commitTextarea,
|
|
1133
|
+
placeholder: t("commit.placeholder"),
|
|
1134
|
+
value: commitMessage,
|
|
1135
|
+
onChange: (e) => {
|
|
1136
|
+
setCommitMessage(e.target.value);
|
|
1137
|
+
},
|
|
1138
|
+
onKeyDown: handleCommitKeyDown
|
|
1139
|
+
}), (0, react_jsx_runtime.jsxs)("div", {
|
|
1140
|
+
className: GitBody_module_css_default.commitButtonRow,
|
|
1141
|
+
children: [(0, react_jsx_runtime.jsx)("button", {
|
|
1142
|
+
type: "button",
|
|
1143
|
+
className: GitBody_module_css_default.commitPushBtn,
|
|
1144
|
+
disabled: committing || stagedCount === 0,
|
|
1145
|
+
onClick: () => {
|
|
1146
|
+
handleCommit(true);
|
|
1147
|
+
},
|
|
1148
|
+
children: t("actions.commitAndPush")
|
|
1149
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
1150
|
+
type: "button",
|
|
1151
|
+
className: GitBody_module_css_default.commitBtn,
|
|
1152
|
+
disabled: committing || stagedCount === 0,
|
|
1153
|
+
onClick: () => {
|
|
1154
|
+
handleCommit(false);
|
|
1155
|
+
},
|
|
1156
|
+
children: t("actions.commit")
|
|
1157
|
+
})]
|
|
1158
|
+
})]
|
|
1159
|
+
})
|
|
1160
|
+
] }), selectedFileDiff && (0, react_jsx_runtime.jsxs)("div", {
|
|
1161
|
+
style: { marginTop: "8px" },
|
|
1162
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
1163
|
+
style: {
|
|
1164
|
+
display: "flex",
|
|
1165
|
+
justifyContent: "space-between",
|
|
1166
|
+
alignItems: "center",
|
|
1167
|
+
marginBottom: "4px"
|
|
1168
|
+
},
|
|
1169
|
+
children: [(0, react_jsx_runtime.jsxs)("span", {
|
|
1170
|
+
style: {
|
|
1171
|
+
fontSize: "11px",
|
|
1172
|
+
fontWeight: 600
|
|
1173
|
+
},
|
|
1174
|
+
children: ["差异对比: ", selectedFileDiff.path]
|
|
1175
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
1176
|
+
type: "button",
|
|
1177
|
+
className: GitBody_module_css_default.actionTextBtn,
|
|
1178
|
+
onClick: () => {
|
|
1179
|
+
setSelectedFileDiff(null);
|
|
1180
|
+
},
|
|
1181
|
+
children: "关闭"
|
|
1182
|
+
})]
|
|
1183
|
+
}), (0, react_jsx_runtime.jsx)(DiffViewer, { diffText: selectedFileDiff.diff })]
|
|
1184
|
+
})] }),
|
|
1185
|
+
activeTab === "tree" && (0, react_jsx_runtime.jsxs)("div", {
|
|
1186
|
+
style: {
|
|
1187
|
+
display: "flex",
|
|
1188
|
+
flexDirection: "column",
|
|
1189
|
+
flex: "1 1 auto",
|
|
1190
|
+
minHeight: 0,
|
|
1191
|
+
overflow: "hidden"
|
|
1192
|
+
},
|
|
1193
|
+
children: [
|
|
1194
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
1195
|
+
className: GitBody_module_css_default.treeFilterRow,
|
|
1196
|
+
children: [(0, react_jsx_runtime.jsx)("input", {
|
|
1197
|
+
className: GitBody_module_css_default.treeSearchInput,
|
|
1198
|
+
placeholder: t("tree.searchPlaceholder"),
|
|
1199
|
+
value: treeSearch,
|
|
1200
|
+
onChange: (e) => {
|
|
1201
|
+
setTreeSearch(e.target.value);
|
|
1202
|
+
}
|
|
1203
|
+
}), (0, react_jsx_runtime.jsxs)("div", {
|
|
1204
|
+
className: GitBody_module_css_default.mainlineToggleGroup,
|
|
1205
|
+
children: [(0, react_jsx_runtime.jsx)("button", {
|
|
1206
|
+
type: "button",
|
|
1207
|
+
className: `${GitBody_module_css_default.mainlineToggleBtn} ${filterMode === "all" ? GitBody_module_css_default.mainlineToggleBtnActive : ""}`,
|
|
1208
|
+
onClick: () => {
|
|
1209
|
+
setFilterMode("all");
|
|
1210
|
+
},
|
|
1211
|
+
children: t("tree.filterAll")
|
|
1212
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
1213
|
+
type: "button",
|
|
1214
|
+
className: `${GitBody_module_css_default.mainlineToggleBtn} ${filterMode === "mainline" ? GitBody_module_css_default.mainlineToggleBtnActive : ""}`,
|
|
1215
|
+
onClick: () => {
|
|
1216
|
+
setFilterMode("mainline");
|
|
1217
|
+
},
|
|
1218
|
+
children: t("tree.filterMainline")
|
|
1219
|
+
})]
|
|
1220
|
+
})]
|
|
1221
|
+
}),
|
|
1222
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
1223
|
+
className: GitBody_module_css_default.workstationLayout,
|
|
1224
|
+
style: { "--git-graph-col-width": `${graphColWidth}px` },
|
|
1225
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
1226
|
+
className: GitBody_module_css_default.tablePane,
|
|
1227
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
1228
|
+
className: GitBody_module_css_default.treeTableHeader,
|
|
1229
|
+
children: [
|
|
1230
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
1231
|
+
className: GitBody_module_css_default.colHeaderTitle,
|
|
1232
|
+
children: t("tree.colGraph")
|
|
1233
|
+
}),
|
|
1234
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
1235
|
+
className: GitBody_module_css_default.colHeaderTitle,
|
|
1236
|
+
children: t("tree.colSubject")
|
|
1237
|
+
}),
|
|
1238
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
1239
|
+
className: GitBody_module_css_default.colHeaderTitle,
|
|
1240
|
+
children: t("tree.colAuthor")
|
|
1241
|
+
}),
|
|
1242
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
1243
|
+
className: GitBody_module_css_default.colHeaderTitle,
|
|
1244
|
+
children: t("tree.colTime")
|
|
1245
|
+
}),
|
|
1246
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
1247
|
+
className: GitBody_module_css_default.colHeaderTitle,
|
|
1248
|
+
children: t("tree.colSha")
|
|
1249
|
+
})
|
|
1250
|
+
]
|
|
1251
|
+
}), (0, react_jsx_runtime.jsxs)("div", {
|
|
1252
|
+
className: GitBody_module_css_default.treeContainer,
|
|
1253
|
+
style: { position: "relative" },
|
|
1254
|
+
children: [(0, react_jsx_runtime.jsxs)("svg", {
|
|
1255
|
+
className: GitBody_module_css_default.graphOverlaySvg,
|
|
1256
|
+
style: {
|
|
1257
|
+
width: `${graphColWidth}px`,
|
|
1258
|
+
height: `${filteredCommits.length * 28}px`
|
|
1259
|
+
},
|
|
1260
|
+
children: [dagGraph.edges.map((e) => (0, react_jsx_runtime.jsx)("path", {
|
|
1261
|
+
d: e.d,
|
|
1262
|
+
stroke: e.color,
|
|
1263
|
+
strokeWidth: 2,
|
|
1264
|
+
fill: "none",
|
|
1265
|
+
strokeLinecap: "round"
|
|
1266
|
+
}, e.key)), dagGraph.nodes.map((n) => {
|
|
1267
|
+
return (0, react_jsx_runtime.jsxs)("g", { children: [
|
|
1268
|
+
highlightedCommitHash === n.hash && (0, react_jsx_runtime.jsx)("circle", {
|
|
1269
|
+
cx: n.x,
|
|
1270
|
+
cy: n.y,
|
|
1271
|
+
r: 8.5,
|
|
1272
|
+
className: GitBody_module_css_default.locateGlowRing
|
|
1273
|
+
}),
|
|
1274
|
+
n.hasTag && (0, react_jsx_runtime.jsx)("circle", {
|
|
1275
|
+
cx: n.x,
|
|
1276
|
+
cy: n.y,
|
|
1277
|
+
r: 6.5,
|
|
1278
|
+
stroke: "#f0883e",
|
|
1279
|
+
strokeWidth: 1.5,
|
|
1280
|
+
fill: "none",
|
|
1281
|
+
opacity: .9
|
|
1282
|
+
}),
|
|
1283
|
+
n.isHead && !n.hasTag && (0, react_jsx_runtime.jsx)("circle", {
|
|
1284
|
+
cx: n.x,
|
|
1285
|
+
cy: n.y,
|
|
1286
|
+
r: 6.5,
|
|
1287
|
+
stroke: n.color,
|
|
1288
|
+
strokeWidth: 1.5,
|
|
1289
|
+
fill: "none",
|
|
1290
|
+
opacity: .8
|
|
1291
|
+
}),
|
|
1292
|
+
(0, react_jsx_runtime.jsx)("circle", {
|
|
1293
|
+
cx: n.x,
|
|
1294
|
+
cy: n.y,
|
|
1295
|
+
r: 4,
|
|
1296
|
+
fill: n.color
|
|
1297
|
+
})
|
|
1298
|
+
] }, n.hash);
|
|
1299
|
+
})]
|
|
1300
|
+
}), filteredCommits.map((c) => {
|
|
1301
|
+
const isSelected = selectedCommitHash === c.hash;
|
|
1302
|
+
const isHighlighted = highlightedCommitHash === c.hash;
|
|
1303
|
+
const parsed = parseConventionalCommit(c.subject);
|
|
1304
|
+
const avatar = getAuthorAvatar(c.author);
|
|
1305
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
1306
|
+
id: `git-commit-${c.hash}`,
|
|
1307
|
+
className: [
|
|
1308
|
+
GitBody_module_css_default.treeRowGrid,
|
|
1309
|
+
isSelected ? GitBody_module_css_default.treeRowGridSelected : "",
|
|
1310
|
+
isHighlighted ? GitBody_module_css_default.treeRowHighlighted : ""
|
|
1311
|
+
].filter(Boolean).join(" "),
|
|
1312
|
+
onClick: () => {
|
|
1313
|
+
handleSelectCommit(c.hash);
|
|
1314
|
+
},
|
|
1315
|
+
children: [
|
|
1316
|
+
(0, react_jsx_runtime.jsx)("div", { style: {
|
|
1317
|
+
width: `${graphColWidth}px`,
|
|
1318
|
+
height: 28,
|
|
1319
|
+
flexShrink: 0
|
|
1320
|
+
} }),
|
|
1321
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
1322
|
+
className: GitBody_module_css_default.subjectCol,
|
|
1323
|
+
children: [
|
|
1324
|
+
c.refs?.map((ref, idx) => {
|
|
1325
|
+
let refClass = GitBody_module_css_default.refBranch;
|
|
1326
|
+
let refText = ref;
|
|
1327
|
+
if (ref.startsWith("tag: ")) {
|
|
1328
|
+
refClass = GitBody_module_css_default.refTag;
|
|
1329
|
+
refText = `🏷️ ${ref.slice(5)}`;
|
|
1330
|
+
} else if (ref.includes("HEAD")) refClass = GitBody_module_css_default.refHead;
|
|
1331
|
+
else if (ref.startsWith("origin/")) refClass = GitBody_module_css_default.refRemote;
|
|
1332
|
+
return (0, react_jsx_runtime.jsx)("span", {
|
|
1333
|
+
className: `${GitBody_module_css_default.refBadge} ${refClass}`,
|
|
1334
|
+
title: ref,
|
|
1335
|
+
children: refText
|
|
1336
|
+
}, idx);
|
|
1337
|
+
}),
|
|
1338
|
+
parsed.type && (0, react_jsx_runtime.jsx)("span", {
|
|
1339
|
+
className: `${GitBody_module_css_default.typeBadge} ${getTypeBadgeClass(parsed.type)}`,
|
|
1340
|
+
children: parsed.type
|
|
1341
|
+
}),
|
|
1342
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
1343
|
+
className: GitBody_module_css_default.treeSubject,
|
|
1344
|
+
title: c.subject,
|
|
1345
|
+
children: c.subject
|
|
1346
|
+
}),
|
|
1347
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
1348
|
+
className: GitBody_module_css_default.treeRowActions,
|
|
1349
|
+
onClick: (e) => {
|
|
1350
|
+
e.stopPropagation();
|
|
1351
|
+
},
|
|
1352
|
+
children: [
|
|
1353
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
1354
|
+
type: "button",
|
|
1355
|
+
className: GitBody_module_css_default.treeActionBtn,
|
|
1356
|
+
title: "复制完整 SHA",
|
|
1357
|
+
onClick: () => {
|
|
1358
|
+
navigator.clipboard.writeText(c.hash);
|
|
1359
|
+
},
|
|
1360
|
+
children: "SHA"
|
|
1361
|
+
}),
|
|
1362
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
1363
|
+
type: "button",
|
|
1364
|
+
className: GitBody_module_css_default.treeActionBtn,
|
|
1365
|
+
title: "在此提交新建 Tag",
|
|
1366
|
+
onClick: () => {
|
|
1367
|
+
setNewTagCommit(c.shortHash);
|
|
1368
|
+
setCreatingTag(true);
|
|
1369
|
+
setActiveTab("tags");
|
|
1370
|
+
},
|
|
1371
|
+
children: "🏷️"
|
|
1372
|
+
}),
|
|
1373
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
1374
|
+
type: "button",
|
|
1375
|
+
className: GitBody_module_css_default.treeActionBtn,
|
|
1376
|
+
title: "在此提交新建分支",
|
|
1377
|
+
onClick: () => {
|
|
1378
|
+
setCreatingBranch(true);
|
|
1379
|
+
setActiveTab("branches");
|
|
1380
|
+
},
|
|
1381
|
+
children: "⑂"
|
|
1382
|
+
})
|
|
1383
|
+
]
|
|
1384
|
+
})
|
|
1385
|
+
]
|
|
1386
|
+
}),
|
|
1387
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
1388
|
+
className: GitBody_module_css_default.authorCol,
|
|
1389
|
+
title: c.author,
|
|
1390
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
1391
|
+
className: GitBody_module_css_default.authorAvatar,
|
|
1392
|
+
style: { background: avatar.color },
|
|
1393
|
+
children: avatar.initial
|
|
1394
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
1395
|
+
className: GitBody_module_css_default.authorNameText,
|
|
1396
|
+
children: c.author
|
|
1397
|
+
})]
|
|
1398
|
+
}),
|
|
1399
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
1400
|
+
className: GitBody_module_css_default.timeCol,
|
|
1401
|
+
title: c.date,
|
|
1402
|
+
children: c.relativeDate
|
|
1403
|
+
}),
|
|
1404
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
1405
|
+
className: GitBody_module_css_default.shaCol,
|
|
1406
|
+
title: c.hash,
|
|
1407
|
+
children: c.shortHash
|
|
1408
|
+
})
|
|
1409
|
+
]
|
|
1410
|
+
}, c.hash);
|
|
1411
|
+
})]
|
|
1412
|
+
})]
|
|
1413
|
+
}), commitDetail && (0, react_jsx_runtime.jsxs)("div", {
|
|
1414
|
+
className: GitBody_module_css_default.detailsPane,
|
|
1415
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
1416
|
+
className: GitBody_module_css_default.detailsHeader,
|
|
1417
|
+
children: [(0, react_jsx_runtime.jsx)("span", { children: t("detail.title") }), (0, react_jsx_runtime.jsx)("button", {
|
|
1418
|
+
type: "button",
|
|
1419
|
+
className: GitBody_module_css_default.iconButton,
|
|
1420
|
+
title: "关闭详情",
|
|
1421
|
+
onClick: () => {
|
|
1422
|
+
setSelectedCommitHash(null);
|
|
1423
|
+
setCommitDetail(null);
|
|
1424
|
+
},
|
|
1425
|
+
children: "✕"
|
|
1426
|
+
})]
|
|
1427
|
+
}), (0, react_jsx_runtime.jsxs)("div", {
|
|
1428
|
+
className: GitBody_module_css_default.detailsContent,
|
|
1429
|
+
children: [
|
|
1430
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
1431
|
+
className: GitBody_module_css_default.detailsSubject,
|
|
1432
|
+
children: commitDetail.commit.subject
|
|
1433
|
+
}),
|
|
1434
|
+
commitDetail.body && (0, react_jsx_runtime.jsx)("div", {
|
|
1435
|
+
className: GitBody_module_css_default.detailsBody,
|
|
1436
|
+
children: commitDetail.body
|
|
1437
|
+
}),
|
|
1438
|
+
commitDetail.commit.refs && commitDetail.commit.refs.length > 0 && (0, react_jsx_runtime.jsxs)("div", { children: [(0, react_jsx_runtime.jsx)("div", {
|
|
1439
|
+
className: GitBody_module_css_default.detailsSectionTitle,
|
|
1440
|
+
children: t("detail.references")
|
|
1441
|
+
}), (0, react_jsx_runtime.jsx)("div", {
|
|
1442
|
+
style: {
|
|
1443
|
+
display: "flex",
|
|
1444
|
+
flexWrap: "wrap",
|
|
1445
|
+
gap: "4px"
|
|
1446
|
+
},
|
|
1447
|
+
children: commitDetail.commit.refs.map((ref, idx) => {
|
|
1448
|
+
let refClass = GitBody_module_css_default.refBranch;
|
|
1449
|
+
let refText = ref;
|
|
1450
|
+
if (ref.startsWith("tag: ")) {
|
|
1451
|
+
refClass = GitBody_module_css_default.refTag;
|
|
1452
|
+
refText = `🏷️ ${ref.slice(5)}`;
|
|
1453
|
+
} else if (ref.includes("HEAD")) refClass = GitBody_module_css_default.refHead;
|
|
1454
|
+
else if (ref.startsWith("origin/")) refClass = GitBody_module_css_default.refRemote;
|
|
1455
|
+
return (0, react_jsx_runtime.jsx)("span", {
|
|
1456
|
+
className: `${GitBody_module_css_default.refBadge} ${refClass}`,
|
|
1457
|
+
children: refText
|
|
1458
|
+
}, idx);
|
|
1459
|
+
})
|
|
1460
|
+
})] }),
|
|
1461
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
1462
|
+
className: GitBody_module_css_default.detailsMetaGrid,
|
|
1463
|
+
children: [
|
|
1464
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
1465
|
+
className: GitBody_module_css_default.detailsMetaRow,
|
|
1466
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
1467
|
+
className: GitBody_module_css_default.detailsMetaLabel,
|
|
1468
|
+
children: t("detail.author")
|
|
1469
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
1470
|
+
className: GitBody_module_css_default.authorCol,
|
|
1471
|
+
style: { maxWidth: "180px" },
|
|
1472
|
+
children: (() => {
|
|
1473
|
+
const av = getAuthorAvatar(commitDetail.commit.author);
|
|
1474
|
+
return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)("span", {
|
|
1475
|
+
className: GitBody_module_css_default.authorAvatar,
|
|
1476
|
+
style: { background: av.color },
|
|
1477
|
+
children: av.initial
|
|
1478
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
1479
|
+
className: GitBody_module_css_default.authorNameText,
|
|
1480
|
+
children: commitDetail.commit.author
|
|
1481
|
+
})] });
|
|
1482
|
+
})()
|
|
1483
|
+
})]
|
|
1484
|
+
}),
|
|
1485
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
1486
|
+
className: GitBody_module_css_default.detailsMetaRow,
|
|
1487
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
1488
|
+
className: GitBody_module_css_default.detailsMetaLabel,
|
|
1489
|
+
children: t("detail.date")
|
|
1490
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
1491
|
+
className: GitBody_module_css_default.detailsMetaVal,
|
|
1492
|
+
children: formatFullDate(commitDetail.commit.date)
|
|
1493
|
+
})]
|
|
1494
|
+
}),
|
|
1495
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
1496
|
+
className: GitBody_module_css_default.detailsMetaRow,
|
|
1497
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
1498
|
+
className: GitBody_module_css_default.detailsMetaLabel,
|
|
1499
|
+
children: "Commit SHA"
|
|
1500
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
1501
|
+
className: GitBody_module_css_default.tagShaPill,
|
|
1502
|
+
title: "点击复制完整 SHA",
|
|
1503
|
+
onClick: () => {
|
|
1504
|
+
navigator.clipboard.writeText(commitDetail.commit.hash);
|
|
1505
|
+
},
|
|
1506
|
+
children: commitDetail.commit.hash.slice(0, 13)
|
|
1507
|
+
})]
|
|
1508
|
+
}),
|
|
1509
|
+
commitDetail.parents && commitDetail.parents.length > 0 && (0, react_jsx_runtime.jsxs)("div", {
|
|
1510
|
+
className: GitBody_module_css_default.detailsMetaRow,
|
|
1511
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
1512
|
+
className: GitBody_module_css_default.detailsMetaLabel,
|
|
1513
|
+
children: t("detail.parent")
|
|
1514
|
+
}), (0, react_jsx_runtime.jsx)("div", {
|
|
1515
|
+
style: {
|
|
1516
|
+
display: "flex",
|
|
1517
|
+
gap: "4px"
|
|
1518
|
+
},
|
|
1519
|
+
children: commitDetail.parents.map((p) => (0, react_jsx_runtime.jsx)("span", {
|
|
1520
|
+
className: GitBody_module_css_default.detailsParentLink,
|
|
1521
|
+
title: `定位到父提交: ${p}`,
|
|
1522
|
+
onClick: () => {
|
|
1523
|
+
handleLocateCommit(p);
|
|
1524
|
+
},
|
|
1525
|
+
children: p.slice(0, 10)
|
|
1526
|
+
}, p))
|
|
1527
|
+
})]
|
|
1528
|
+
})
|
|
1529
|
+
]
|
|
1530
|
+
}),
|
|
1531
|
+
(0, react_jsx_runtime.jsxs)("div", { children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
1532
|
+
style: {
|
|
1533
|
+
display: "flex",
|
|
1534
|
+
justifyContent: "space-between",
|
|
1535
|
+
alignItems: "center",
|
|
1536
|
+
marginBottom: "6px"
|
|
1537
|
+
},
|
|
1538
|
+
children: [(0, react_jsx_runtime.jsxs)("span", {
|
|
1539
|
+
style: {
|
|
1540
|
+
fontSize: "11px",
|
|
1541
|
+
fontWeight: 600
|
|
1542
|
+
},
|
|
1543
|
+
children: [
|
|
1544
|
+
"变更文件 (",
|
|
1545
|
+
commitDetail.files.length,
|
|
1546
|
+
" 个文件)"
|
|
1547
|
+
]
|
|
1548
|
+
}), (0, react_jsx_runtime.jsxs)("span", {
|
|
1549
|
+
className: GitBody_module_css_default.numstat,
|
|
1550
|
+
children: [(0, react_jsx_runtime.jsxs)("span", {
|
|
1551
|
+
className: GitBody_module_css_default.addStat,
|
|
1552
|
+
children: ["+", commitDetail.totalAdditions]
|
|
1553
|
+
}), (0, react_jsx_runtime.jsxs)("span", {
|
|
1554
|
+
className: GitBody_module_css_default.delStat,
|
|
1555
|
+
children: ["-", commitDetail.totalDeletions]
|
|
1556
|
+
})]
|
|
1557
|
+
})]
|
|
1558
|
+
}), (0, react_jsx_runtime.jsx)("div", {
|
|
1559
|
+
className: GitBody_module_css_default.detailFilesList,
|
|
1560
|
+
children: commitDetail.files.map((f) => (0, react_jsx_runtime.jsxs)("div", {
|
|
1561
|
+
className: GitBody_module_css_default.detailFileItem,
|
|
1562
|
+
onClick: () => {
|
|
1563
|
+
handleViewDiff(f.path, false, commitDetail.commit.hash);
|
|
1564
|
+
},
|
|
1565
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
1566
|
+
className: GitBody_module_css_default.fileLeft,
|
|
1567
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
1568
|
+
className: `${GitBody_module_css_default.statusBadge} ${f.status === "added" ? GitBody_module_css_default.statusA : f.status === "deleted" ? GitBody_module_css_default.statusD : GitBody_module_css_default.statusM}`,
|
|
1569
|
+
children: f.status[0]?.toUpperCase() ?? "M"
|
|
1570
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
1571
|
+
className: GitBody_module_css_default.fileName,
|
|
1572
|
+
children: f.path
|
|
1573
|
+
})]
|
|
1574
|
+
}), (0, react_jsx_runtime.jsxs)("span", {
|
|
1575
|
+
className: GitBody_module_css_default.numstat,
|
|
1576
|
+
children: [(0, react_jsx_runtime.jsxs)("span", {
|
|
1577
|
+
className: GitBody_module_css_default.addStat,
|
|
1578
|
+
children: ["+", f.additions]
|
|
1579
|
+
}), (0, react_jsx_runtime.jsxs)("span", {
|
|
1580
|
+
className: GitBody_module_css_default.delStat,
|
|
1581
|
+
children: ["-", f.deletions]
|
|
1582
|
+
})]
|
|
1583
|
+
})]
|
|
1584
|
+
}, f.path))
|
|
1585
|
+
})] }),
|
|
1586
|
+
selectedFileDiff && (0, react_jsx_runtime.jsxs)("div", {
|
|
1587
|
+
style: { marginTop: "6px" },
|
|
1588
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
1589
|
+
style: {
|
|
1590
|
+
display: "flex",
|
|
1591
|
+
justifyContent: "space-between",
|
|
1592
|
+
alignItems: "center",
|
|
1593
|
+
marginBottom: "4px"
|
|
1594
|
+
},
|
|
1595
|
+
children: [(0, react_jsx_runtime.jsxs)("span", {
|
|
1596
|
+
style: {
|
|
1597
|
+
fontSize: "11px",
|
|
1598
|
+
fontWeight: 600
|
|
1599
|
+
},
|
|
1600
|
+
children: ["差异: ", selectedFileDiff.path]
|
|
1601
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
1602
|
+
type: "button",
|
|
1603
|
+
className: GitBody_module_css_default.actionTextBtn,
|
|
1604
|
+
onClick: () => {
|
|
1605
|
+
setSelectedFileDiff(null);
|
|
1606
|
+
},
|
|
1607
|
+
children: "关闭"
|
|
1608
|
+
})]
|
|
1609
|
+
}), (0, react_jsx_runtime.jsx)(DiffViewer, { diffText: selectedFileDiff.diff })]
|
|
1610
|
+
}),
|
|
1611
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
1612
|
+
className: GitBody_module_css_default.detailsBottomActions,
|
|
1613
|
+
children: [(0, react_jsx_runtime.jsx)("button", {
|
|
1614
|
+
type: "button",
|
|
1615
|
+
className: GitBody_module_css_default.actionTextBtn,
|
|
1616
|
+
style: {
|
|
1617
|
+
flex: 1,
|
|
1618
|
+
padding: "5px"
|
|
1619
|
+
},
|
|
1620
|
+
onClick: () => {
|
|
1621
|
+
handleCheckoutBranch(commitDetail.commit.shortHash);
|
|
1622
|
+
},
|
|
1623
|
+
children: t("detail.checkout")
|
|
1624
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
1625
|
+
type: "button",
|
|
1626
|
+
className: GitBody_module_css_default.commitBtn,
|
|
1627
|
+
style: {
|
|
1628
|
+
flex: 1,
|
|
1629
|
+
padding: "5px"
|
|
1630
|
+
},
|
|
1631
|
+
onClick: () => {
|
|
1632
|
+
setNewTagCommit(commitDetail.commit.shortHash);
|
|
1633
|
+
setCreatingTag(true);
|
|
1634
|
+
setActiveTab("tags");
|
|
1635
|
+
},
|
|
1636
|
+
children: t("detail.createBranchOrTag")
|
|
1637
|
+
})]
|
|
1638
|
+
})
|
|
1639
|
+
]
|
|
1640
|
+
})]
|
|
1641
|
+
})]
|
|
1642
|
+
}),
|
|
1643
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
1644
|
+
className: GitBody_module_css_default.treeStatusFooter,
|
|
1645
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
1646
|
+
className: GitBody_module_css_default.footerSyncStatus,
|
|
1647
|
+
children: [(0, react_jsx_runtime.jsx)("span", { className: GitBody_module_css_default.syncDot }), (0, react_jsx_runtime.jsx)("span", { children: status.ahead === 0 && status.behind === 0 ? t("footer.syncNormal") : status.ahead > 0 ? t("footer.ahead", { count: status.ahead }) : t("footer.behind", { count: status.behind }) })]
|
|
1648
|
+
}), (0, react_jsx_runtime.jsxs)("div", {
|
|
1649
|
+
className: GitBody_module_css_default.footerStats,
|
|
1650
|
+
children: [(0, react_jsx_runtime.jsx)("span", { children: t("footer.showingCount", {
|
|
1651
|
+
count: filteredCommits.length,
|
|
1652
|
+
total: status.totalCommitsCount ?? commits.length
|
|
1653
|
+
}) }), status.totalCommitsCount && commits.length < status.totalCommitsCount && (0, react_jsx_runtime.jsx)("span", {
|
|
1654
|
+
className: GitBody_module_css_default.loadMoreLink,
|
|
1655
|
+
onClick: () => {
|
|
1656
|
+
handleLoadMore();
|
|
1657
|
+
},
|
|
1658
|
+
children: t("footer.loadMore")
|
|
1659
|
+
})]
|
|
1660
|
+
})]
|
|
1661
|
+
})
|
|
1662
|
+
]
|
|
1663
|
+
}),
|
|
1664
|
+
activeTab === "branches" && (0, react_jsx_runtime.jsxs)("div", {
|
|
1665
|
+
style: {
|
|
1666
|
+
display: "flex",
|
|
1667
|
+
flexDirection: "column",
|
|
1668
|
+
gap: "8px"
|
|
1669
|
+
},
|
|
1670
|
+
children: [
|
|
1671
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
1672
|
+
style: {
|
|
1673
|
+
display: "flex",
|
|
1674
|
+
gap: "6px"
|
|
1675
|
+
},
|
|
1676
|
+
children: [(0, react_jsx_runtime.jsx)("input", {
|
|
1677
|
+
className: GitBody_module_css_default.commitTextarea,
|
|
1678
|
+
style: {
|
|
1679
|
+
minHeight: "30px",
|
|
1680
|
+
height: "30px",
|
|
1681
|
+
padding: "4px 8px"
|
|
1682
|
+
},
|
|
1683
|
+
placeholder: t("branch.filter"),
|
|
1684
|
+
value: branchFilter,
|
|
1685
|
+
onChange: (e) => {
|
|
1686
|
+
setBranchFilter(e.target.value);
|
|
1687
|
+
}
|
|
1688
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
1689
|
+
type: "button",
|
|
1690
|
+
className: GitBody_module_css_default.actionTextBtn,
|
|
1691
|
+
style: { flexShrink: 0 },
|
|
1692
|
+
onClick: () => {
|
|
1693
|
+
setCreatingBranch((prev) => !prev);
|
|
1694
|
+
},
|
|
1695
|
+
children: "+ 新建分支"
|
|
1696
|
+
})]
|
|
1697
|
+
}),
|
|
1698
|
+
creatingBranch && (0, react_jsx_runtime.jsxs)("div", {
|
|
1699
|
+
style: {
|
|
1700
|
+
display: "flex",
|
|
1701
|
+
gap: "6px"
|
|
1702
|
+
},
|
|
1703
|
+
children: [(0, react_jsx_runtime.jsx)("input", {
|
|
1704
|
+
autoFocus: true,
|
|
1705
|
+
className: GitBody_module_css_default.commitTextarea,
|
|
1706
|
+
style: {
|
|
1707
|
+
minHeight: "30px",
|
|
1708
|
+
height: "30px",
|
|
1709
|
+
padding: "4px 8px"
|
|
1710
|
+
},
|
|
1711
|
+
placeholder: "新分支名称...",
|
|
1712
|
+
value: newBranchName,
|
|
1713
|
+
onChange: (e) => {
|
|
1714
|
+
setNewBranchName(e.target.value);
|
|
1715
|
+
},
|
|
1716
|
+
onKeyDown: (e) => {
|
|
1717
|
+
if (e.key === "Enter") {
|
|
1718
|
+
const trimmed = newBranchName.trim();
|
|
1719
|
+
if (trimmed) handleCheckoutBranch(trimmed, true);
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
1723
|
+
type: "button",
|
|
1724
|
+
className: GitBody_module_css_default.commitBtn,
|
|
1725
|
+
onClick: () => {
|
|
1726
|
+
const trimmed = newBranchName.trim();
|
|
1727
|
+
if (trimmed) handleCheckoutBranch(trimmed, true);
|
|
1728
|
+
},
|
|
1729
|
+
children: "创建并检出"
|
|
1730
|
+
})]
|
|
1731
|
+
}),
|
|
1732
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
1733
|
+
className: GitBody_module_css_default.section,
|
|
1734
|
+
children: [(0, react_jsx_runtime.jsx)("div", {
|
|
1735
|
+
className: GitBody_module_css_default.sectionHeader,
|
|
1736
|
+
children: (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
1737
|
+
"本地分支 (",
|
|
1738
|
+
filteredLocalBranches.length,
|
|
1739
|
+
")"
|
|
1740
|
+
] })
|
|
1741
|
+
}), (0, react_jsx_runtime.jsx)("div", {
|
|
1742
|
+
className: GitBody_module_css_default.fileList,
|
|
1743
|
+
children: filteredLocalBranches.map((b) => (0, react_jsx_runtime.jsxs)("div", {
|
|
1744
|
+
className: GitBody_module_css_default.fileItem,
|
|
1745
|
+
style: { background: b.isCurrent ? "rgba(56, 139, 253, 0.15)" : void 0 },
|
|
1746
|
+
onClick: () => {
|
|
1747
|
+
if (!b.isCurrent) handleCheckoutBranch(b.name);
|
|
1748
|
+
},
|
|
1749
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
1750
|
+
className: GitBody_module_css_default.fileLeft,
|
|
1751
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
1752
|
+
style: { color: b.isCurrent ? "#388bfd" : "inherit" },
|
|
1753
|
+
children: b.isCurrent ? "●" : "○"
|
|
1754
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
1755
|
+
style: { fontWeight: b.isCurrent ? 600 : 400 },
|
|
1756
|
+
children: b.name
|
|
1757
|
+
})]
|
|
1758
|
+
}), b.isCurrent && (0, react_jsx_runtime.jsx)("span", {
|
|
1759
|
+
style: {
|
|
1760
|
+
fontSize: "11px",
|
|
1761
|
+
color: "#58a6ff"
|
|
1762
|
+
},
|
|
1763
|
+
children: "当前检出"
|
|
1764
|
+
})]
|
|
1765
|
+
}, b.name))
|
|
1766
|
+
})]
|
|
1767
|
+
}),
|
|
1768
|
+
filteredRemoteBranches.length > 0 && (0, react_jsx_runtime.jsxs)("div", {
|
|
1769
|
+
className: GitBody_module_css_default.section,
|
|
1770
|
+
children: [(0, react_jsx_runtime.jsx)("div", {
|
|
1771
|
+
className: GitBody_module_css_default.sectionHeader,
|
|
1772
|
+
children: (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
1773
|
+
"远程分支 (",
|
|
1774
|
+
filteredRemoteBranches.length,
|
|
1775
|
+
")"
|
|
1776
|
+
] })
|
|
1777
|
+
}), (0, react_jsx_runtime.jsx)("div", {
|
|
1778
|
+
className: GitBody_module_css_default.fileList,
|
|
1779
|
+
children: filteredRemoteBranches.map((b) => (0, react_jsx_runtime.jsx)("div", {
|
|
1780
|
+
className: GitBody_module_css_default.fileItem,
|
|
1781
|
+
onClick: () => {
|
|
1782
|
+
handleCheckoutBranch(b.name);
|
|
1783
|
+
},
|
|
1784
|
+
children: (0, react_jsx_runtime.jsxs)("div", {
|
|
1785
|
+
className: GitBody_module_css_default.fileLeft,
|
|
1786
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
1787
|
+
style: { opacity: .6 },
|
|
1788
|
+
children: "☁"
|
|
1789
|
+
}), (0, react_jsx_runtime.jsx)("span", { children: b.name })]
|
|
1790
|
+
})
|
|
1791
|
+
}, b.name))
|
|
1792
|
+
})]
|
|
1793
|
+
})
|
|
1794
|
+
]
|
|
1795
|
+
}),
|
|
1796
|
+
activeTab === "tags" && (0, react_jsx_runtime.jsxs)("div", {
|
|
1797
|
+
style: {
|
|
1798
|
+
display: "flex",
|
|
1799
|
+
flexDirection: "column",
|
|
1800
|
+
gap: "8px"
|
|
1801
|
+
},
|
|
1802
|
+
children: [
|
|
1803
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
1804
|
+
style: {
|
|
1805
|
+
display: "flex",
|
|
1806
|
+
gap: "6px"
|
|
1807
|
+
},
|
|
1808
|
+
children: [(0, react_jsx_runtime.jsx)("input", {
|
|
1809
|
+
className: GitBody_module_css_default.commitTextarea,
|
|
1810
|
+
style: {
|
|
1811
|
+
minHeight: "30px",
|
|
1812
|
+
height: "30px",
|
|
1813
|
+
padding: "4px 8px"
|
|
1814
|
+
},
|
|
1815
|
+
placeholder: t("tag.filter"),
|
|
1816
|
+
value: tagFilter,
|
|
1817
|
+
onChange: (e) => {
|
|
1818
|
+
setTagFilter(e.target.value);
|
|
1819
|
+
}
|
|
1820
|
+
}), (0, react_jsx_runtime.jsxs)("button", {
|
|
1821
|
+
type: "button",
|
|
1822
|
+
className: GitBody_module_css_default.actionTextBtn,
|
|
1823
|
+
style: { flexShrink: 0 },
|
|
1824
|
+
onClick: () => {
|
|
1825
|
+
setCreatingTag((prev) => !prev);
|
|
1826
|
+
},
|
|
1827
|
+
children: ["+ ", t("tag.newPrompt")]
|
|
1828
|
+
})]
|
|
1829
|
+
}),
|
|
1830
|
+
creatingTag && (0, react_jsx_runtime.jsxs)("div", {
|
|
1831
|
+
className: GitBody_module_css_default.tagForm,
|
|
1832
|
+
children: [
|
|
1833
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
1834
|
+
className: GitBody_module_css_default.tagFormTitle,
|
|
1835
|
+
children: t("tag.newPrompt")
|
|
1836
|
+
}),
|
|
1837
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
1838
|
+
style: {
|
|
1839
|
+
display: "flex",
|
|
1840
|
+
flexDirection: "column",
|
|
1841
|
+
gap: "4px"
|
|
1842
|
+
},
|
|
1843
|
+
children: [(0, react_jsx_runtime.jsxs)("label", {
|
|
1844
|
+
style: {
|
|
1845
|
+
fontSize: "11px",
|
|
1846
|
+
color: "var(--dsw-alias-label-secondary)"
|
|
1847
|
+
},
|
|
1848
|
+
children: [t("tag.nameLabel"), " *"]
|
|
1849
|
+
}), (0, react_jsx_runtime.jsx)("input", {
|
|
1850
|
+
autoFocus: true,
|
|
1851
|
+
className: GitBody_module_css_default.commitTextarea,
|
|
1852
|
+
style: {
|
|
1853
|
+
minHeight: "28px",
|
|
1854
|
+
height: "28px",
|
|
1855
|
+
padding: "4px 8px"
|
|
1856
|
+
},
|
|
1857
|
+
placeholder: t("tag.namePlaceholder"),
|
|
1858
|
+
value: newTagName,
|
|
1859
|
+
onChange: (e) => {
|
|
1860
|
+
setNewTagName(e.target.value);
|
|
1861
|
+
}
|
|
1862
|
+
})]
|
|
1863
|
+
}),
|
|
1864
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
1865
|
+
style: {
|
|
1866
|
+
display: "flex",
|
|
1867
|
+
flexDirection: "column",
|
|
1868
|
+
gap: "4px"
|
|
1869
|
+
},
|
|
1870
|
+
children: [(0, react_jsx_runtime.jsx)("label", {
|
|
1871
|
+
style: {
|
|
1872
|
+
fontSize: "11px",
|
|
1873
|
+
color: "var(--dsw-alias-label-secondary)"
|
|
1874
|
+
},
|
|
1875
|
+
children: t("tag.targetCommitLabel")
|
|
1876
|
+
}), (0, react_jsx_runtime.jsx)("input", {
|
|
1877
|
+
className: GitBody_module_css_default.commitTextarea,
|
|
1878
|
+
style: {
|
|
1879
|
+
minHeight: "28px",
|
|
1880
|
+
height: "28px",
|
|
1881
|
+
padding: "4px 8px"
|
|
1882
|
+
},
|
|
1883
|
+
placeholder: "例如 687f282 或留空为 HEAD",
|
|
1884
|
+
value: newTagCommit,
|
|
1885
|
+
onChange: (e) => {
|
|
1886
|
+
setNewTagCommit(e.target.value);
|
|
1887
|
+
}
|
|
1888
|
+
})]
|
|
1889
|
+
}),
|
|
1890
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
1891
|
+
style: {
|
|
1892
|
+
display: "flex",
|
|
1893
|
+
flexDirection: "column",
|
|
1894
|
+
gap: "4px"
|
|
1895
|
+
},
|
|
1896
|
+
children: [(0, react_jsx_runtime.jsx)("label", {
|
|
1897
|
+
style: {
|
|
1898
|
+
fontSize: "11px",
|
|
1899
|
+
color: "var(--dsw-alias-label-secondary)"
|
|
1900
|
+
},
|
|
1901
|
+
children: t("tag.messageLabel")
|
|
1902
|
+
}), (0, react_jsx_runtime.jsx)("input", {
|
|
1903
|
+
className: GitBody_module_css_default.commitTextarea,
|
|
1904
|
+
style: {
|
|
1905
|
+
minHeight: "28px",
|
|
1906
|
+
height: "28px",
|
|
1907
|
+
padding: "4px 8px"
|
|
1908
|
+
},
|
|
1909
|
+
placeholder: t("tag.messagePrompt"),
|
|
1910
|
+
value: newTagMessage,
|
|
1911
|
+
onChange: (e) => {
|
|
1912
|
+
setNewTagMessage(e.target.value);
|
|
1913
|
+
}
|
|
1914
|
+
})]
|
|
1915
|
+
}),
|
|
1916
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
1917
|
+
className: GitBody_module_css_default.tagFormActions,
|
|
1918
|
+
children: [(0, react_jsx_runtime.jsx)("button", {
|
|
1919
|
+
type: "button",
|
|
1920
|
+
className: GitBody_module_css_default.actionTextBtn,
|
|
1921
|
+
onClick: () => {
|
|
1922
|
+
setCreatingTag(false);
|
|
1923
|
+
},
|
|
1924
|
+
children: t("tag.cancelBtn")
|
|
1925
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
1926
|
+
type: "button",
|
|
1927
|
+
className: GitBody_module_css_default.commitBtn,
|
|
1928
|
+
onClick: () => {
|
|
1929
|
+
handleCreateTag();
|
|
1930
|
+
},
|
|
1931
|
+
children: t("tag.createBtn")
|
|
1932
|
+
})]
|
|
1933
|
+
})
|
|
1934
|
+
]
|
|
1935
|
+
}),
|
|
1936
|
+
filteredTags.length === 0 ? (0, react_jsx_runtime.jsxs)("div", {
|
|
1937
|
+
className: GitBody_module_css_default.emptyState,
|
|
1938
|
+
children: [(0, react_jsx_runtime.jsx)("svg", {
|
|
1939
|
+
viewBox: "0 0 16 16",
|
|
1940
|
+
fill: "currentColor",
|
|
1941
|
+
children: (0, react_jsx_runtime.jsx)("path", { d: "M1 7.775V2.75C1 1.784 1.784 1 2.75 1h5.025c.464 0 .91.184 1.238.513l6.25 6.25a1.75 1.75 0 0 1 0 2.474l-5.026 5.026a1.75 1.75 0 0 1-2.474 0l-6.25-6.25A1.752 1.752 0 0 1 1 7.775zm1.5 0c0 .066.026.13.073.177l6.25 6.25a.25.25 0 0 0 .354 0l5.025-5.025a.25.25 0 0 0 0-.354l-6.25-6.25a.25.25 0 0 0-.177-.073H2.75a.25.25 0 0 0-.25.25v5.025zM6 4.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" })
|
|
1942
|
+
}), (0, react_jsx_runtime.jsx)("div", { children: t("tag.empty") })]
|
|
1943
|
+
}) : (0, react_jsx_runtime.jsx)("div", {
|
|
1944
|
+
className: GitBody_module_css_default.tagList,
|
|
1945
|
+
children: filteredTags.map((tag) => (0, react_jsx_runtime.jsxs)("div", {
|
|
1946
|
+
className: GitBody_module_css_default.tagCard,
|
|
1947
|
+
children: [
|
|
1948
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
1949
|
+
className: GitBody_module_css_default.tagCardHeader,
|
|
1950
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
1951
|
+
className: GitBody_module_css_default.tagTitleRow,
|
|
1952
|
+
children: [
|
|
1953
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
1954
|
+
style: { fontSize: "13px" },
|
|
1955
|
+
children: "🏷️"
|
|
1956
|
+
}),
|
|
1957
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
1958
|
+
className: GitBody_module_css_default.tagName,
|
|
1959
|
+
title: "点击在图谱中定位",
|
|
1960
|
+
onClick: () => {
|
|
1961
|
+
handleLocateCommit(tag.commitHash, tag.name);
|
|
1962
|
+
},
|
|
1963
|
+
children: tag.name
|
|
1964
|
+
}),
|
|
1965
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
1966
|
+
className: GitBody_module_css_default.tagShaPill,
|
|
1967
|
+
title: `Commit: ${tag.commitHash} (点击在图谱中定位)`,
|
|
1968
|
+
onClick: () => {
|
|
1969
|
+
handleLocateCommit(tag.commitHash, tag.name);
|
|
1970
|
+
},
|
|
1971
|
+
children: tag.shortHash
|
|
1972
|
+
}),
|
|
1973
|
+
tag.isAnnotated && (0, react_jsx_runtime.jsx)("span", {
|
|
1974
|
+
className: GitBody_module_css_default.tagAnnotatedBadge,
|
|
1975
|
+
children: t("tag.annotated")
|
|
1976
|
+
})
|
|
1977
|
+
]
|
|
1978
|
+
}), (0, react_jsx_runtime.jsxs)("div", {
|
|
1979
|
+
className: GitBody_module_css_default.tagActions,
|
|
1980
|
+
children: [
|
|
1981
|
+
(0, react_jsx_runtime.jsxs)("button", {
|
|
1982
|
+
type: "button",
|
|
1983
|
+
className: GitBody_module_css_default.tagLocateBtn,
|
|
1984
|
+
title: "在图谱中定位该提交",
|
|
1985
|
+
onClick: () => {
|
|
1986
|
+
handleLocateCommit(tag.commitHash, tag.name);
|
|
1987
|
+
},
|
|
1988
|
+
children: [(0, react_jsx_runtime.jsx)("span", { children: "🎯" }), (0, react_jsx_runtime.jsx)("span", { children: t("tag.locateBtn") })]
|
|
1989
|
+
}),
|
|
1990
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
1991
|
+
type: "button",
|
|
1992
|
+
className: GitBody_module_css_default.fileMiniBtn,
|
|
1993
|
+
title: t("tag.copyName"),
|
|
1994
|
+
onClick: () => {
|
|
1995
|
+
navigator.clipboard.writeText(tag.name);
|
|
1996
|
+
},
|
|
1997
|
+
children: "📋"
|
|
1998
|
+
}),
|
|
1999
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
2000
|
+
type: "button",
|
|
2001
|
+
className: GitBody_module_css_default.fileMiniBtn,
|
|
2002
|
+
title: t("tag.deleteBtn"),
|
|
2003
|
+
onClick: () => {
|
|
2004
|
+
handleDeleteTag(tag.name);
|
|
2005
|
+
},
|
|
2006
|
+
children: "🗑️"
|
|
2007
|
+
})
|
|
2008
|
+
]
|
|
2009
|
+
})]
|
|
2010
|
+
}),
|
|
2011
|
+
tag.message && (0, react_jsx_runtime.jsx)("div", {
|
|
2012
|
+
className: GitBody_module_css_default.tagMessage,
|
|
2013
|
+
title: tag.message,
|
|
2014
|
+
children: tag.message
|
|
2015
|
+
}),
|
|
2016
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
2017
|
+
className: GitBody_module_css_default.tagMetaFooter,
|
|
2018
|
+
children: [(0, react_jsx_runtime.jsxs)("span", {
|
|
2019
|
+
className: GitBody_module_css_default.tagAuthor,
|
|
2020
|
+
children: [(0, react_jsx_runtime.jsx)("span", { children: "👤" }), (0, react_jsx_runtime.jsx)("span", { children: tag.author })]
|
|
2021
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
2022
|
+
title: tag.date,
|
|
2023
|
+
children: tag.relativeDate
|
|
2024
|
+
})]
|
|
2025
|
+
})
|
|
2026
|
+
]
|
|
2027
|
+
}, tag.name))
|
|
2028
|
+
})
|
|
2029
|
+
]
|
|
2030
|
+
})
|
|
2031
|
+
]
|
|
2032
|
+
})
|
|
2033
|
+
]
|
|
2034
|
+
});
|
|
2035
|
+
});
|
|
2036
|
+
//#endregion
|
|
2037
|
+
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/experimental/git/src/client/GitBranchPill.module.css.mjs
|
|
2038
|
+
const css = ".F_1oUa_anchor{min-width:0;font-size:calc(var(--dsh-content-font-size-secondary,13px) - 1px);line-height:calc(20px + var(--dsh-content-font-delta-secondary,0px));display:inline-flex;position:relative}.F_1oUa_pill{box-sizing:border-box;border-radius:var(--dsw-radius-sm);max-width:100%;color:var(--dsw-alias-label-tertiary);font:inherit;font-variant-numeric:tabular-nums;font-weight:500;line-height:inherit;white-space:nowrap;cursor:pointer;background:0 0;border:none;align-items:center;gap:6px;padding:1px 8px;transition:background .15s,color .15s;display:inline-flex}.F_1oUa_pill:hover,.F_1oUa_pill[aria-expanded=true]{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.F_1oUa_icon{width:14px;height:14px;color:var(--dsw-alias-label-tertiary);flex:none}.F_1oUa_pill:hover .F_1oUa_icon,.F_1oUa_pill[aria-expanded=true] .F_1oUa_icon{color:var(--dsw-alias-state-business-primary)}.F_1oUa_branchName{text-overflow:ellipsis;white-space:nowrap;max-width:150px;overflow:hidden}.F_1oUa_badge{border-radius:var(--dsw-radius-xs,3px);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary);align-items:center;padding:0 4px;font-size:11px;font-weight:500;line-height:14px;display:inline-flex}.F_1oUa_badgeAhead{color:var(--dsw-alias-state-business-primary)}.F_1oUa_badgeBehind{color:var(--dsw-alias-state-warn-primary)}.F_1oUa_popover{z-index:1100;box-sizing:border-box;border-radius:var(--dsw-radius-lg);--dsw-elevation-stroke-color:var(--dsw-alias-border-l1);width:310px;max-height:440px;box-shadow:var(--dsw-elevation-prominent);color:var(--dsw-alias-label-primary);cursor:default;border:0;flex-direction:column;font-size:12px;line-height:18px;animation:.15s cubic-bezier(.16,1,.3,1) F_1oUa_popoverFadeIn;display:flex;position:fixed;overflow:hidden}@keyframes F_1oUa_popoverFadeIn{0%{opacity:0;transform:translateY(4px)scale(.98)}to{opacity:1;transform:translateY(0)scale(1)}}.F_1oUa_header{border-bottom:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:6px;padding:8px 10px 6px;display:flex}.F_1oUa_searchRow{border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-interactive-bg-hover);border:.5px solid var(--dsw-alias-border-l2);align-items:center;gap:6px;padding:4px 8px;display:flex}.F_1oUa_searchIcon{width:13px;height:13px;color:var(--dsw-alias-label-tertiary);flex:none}.F_1oUa_searchInput{color:var(--dsw-alias-label-primary);background:0 0;border:none;outline:none;flex:1;font-size:12px}.F_1oUa_searchInput::placeholder{color:var(--dsw-alias-label-tertiary)}.F_1oUa_actionBar{justify-content:space-between;align-items:center;gap:4px;display:flex}.F_1oUa_toolBtnGroup{align-items:center;gap:4px;display:flex}.F_1oUa_toolBtn{border:.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-sm);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary);cursor:pointer;align-items:center;gap:4px;padding:3px 8px;font-family:inherit;font-size:11px;font-weight:500;transition:background .15s,color .15s;display:inline-flex}.F_1oUa_toolBtn:hover{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-primary)}.F_1oUa_btnIcon{flex:none;width:12px;height:12px}.F_1oUa_newBranchBox{gap:6px;margin-top:2px;display:flex}.F_1oUa_newBranchInput{border-radius:var(--dsw-radius-sm);border:.5px solid var(--dsw-alias-state-business-primary);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);outline:none;flex:1;padding:4px 8px;font-size:12px}.F_1oUa_newBranchInput::placeholder{color:var(--dsw-alias-label-tertiary)}.F_1oUa_branchList{flex:1;padding:4px;overflow-y:auto}.F_1oUa_groupLabel{color:var(--dsw-alias-label-tertiary);align-items:center;gap:6px;padding:6px 8px 3px;font-size:11px;font-weight:500;display:flex}.F_1oUa_branchItem{border-radius:var(--dsw-radius-sm);width:100%;color:var(--dsw-alias-label-secondary);font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;justify-content:space-between;align-items:center;padding:5px 8px;font-size:12px;transition:background .12s,color .12s;display:flex}.F_1oUa_branchItem:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.F_1oUa_currentBranch{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-state-business-primary);font-weight:500}.F_1oUa_currentBranch:hover{background:var(--dsw-alias-interactive-bg-active)}.F_1oUa_branchItemLeft{flex:1;align-items:center;gap:6px;min-width:0;display:flex}.F_1oUa_itemIcon{width:13px;height:13px;color:var(--dsw-alias-label-tertiary);flex:none}.F_1oUa_currentBranch .F_1oUa_itemIcon{color:var(--dsw-alias-state-business-primary)}.F_1oUa_itemText{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.F_1oUa_checkMark{width:14px;height:14px;color:var(--dsw-alias-state-business-primary);flex:none}.F_1oUa_emptyTip{text-align:center;color:var(--dsw-alias-label-tertiary);padding:16px 8px;font-size:12px}";
|
|
2039
|
+
const tagId = "@civilization/dsh-experimental-git/GitBranchPill.module.css";
|
|
2040
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
2041
|
+
const tag = document.createElement("style");
|
|
2042
|
+
tag.dataset.plugin = "@civilization/dsh-experimental-git";
|
|
2043
|
+
tag.dataset.pluginCss = tagId;
|
|
2044
|
+
tag.textContent = css;
|
|
2045
|
+
document.head.appendChild(tag);
|
|
2046
|
+
}
|
|
2047
|
+
var GitBranchPill_module_css_default = {
|
|
2048
|
+
"actionBar": "F_1oUa_actionBar",
|
|
2049
|
+
"anchor": "F_1oUa_anchor",
|
|
2050
|
+
"badge": "F_1oUa_badge",
|
|
2051
|
+
"badgeAhead": "F_1oUa_badgeAhead",
|
|
2052
|
+
"badgeBehind": "F_1oUa_badgeBehind",
|
|
2053
|
+
"branchItem": "F_1oUa_branchItem",
|
|
2054
|
+
"branchItemLeft": "F_1oUa_branchItemLeft",
|
|
2055
|
+
"branchList": "F_1oUa_branchList",
|
|
2056
|
+
"branchName": "F_1oUa_branchName",
|
|
2057
|
+
"btnIcon": "F_1oUa_btnIcon",
|
|
2058
|
+
"checkMark": "F_1oUa_checkMark",
|
|
2059
|
+
"currentBranch": "F_1oUa_currentBranch",
|
|
2060
|
+
"emptyTip": "F_1oUa_emptyTip",
|
|
2061
|
+
"groupLabel": "F_1oUa_groupLabel",
|
|
2062
|
+
"header": "F_1oUa_header",
|
|
2063
|
+
"icon": "F_1oUa_icon",
|
|
2064
|
+
"itemIcon": "F_1oUa_itemIcon",
|
|
2065
|
+
"itemText": "F_1oUa_itemText",
|
|
2066
|
+
"newBranchBox": "F_1oUa_newBranchBox",
|
|
2067
|
+
"newBranchInput": "F_1oUa_newBranchInput",
|
|
2068
|
+
"pill": "F_1oUa_pill",
|
|
2069
|
+
"popover": "F_1oUa_popover",
|
|
2070
|
+
"popoverFadeIn": "F_1oUa_popoverFadeIn",
|
|
2071
|
+
"searchIcon": "F_1oUa_searchIcon",
|
|
2072
|
+
"searchInput": "F_1oUa_searchInput",
|
|
2073
|
+
"searchRow": "F_1oUa_searchRow",
|
|
2074
|
+
"toolBtn": "F_1oUa_toolBtn",
|
|
2075
|
+
"toolBtnGroup": "F_1oUa_toolBtnGroup"
|
|
2076
|
+
};
|
|
2077
|
+
//#endregion
|
|
2078
|
+
//#region lib/types/client/GitBranchPill.js
|
|
2079
|
+
/**
|
|
2080
|
+
* Status bar Git branch pill and popover branch switcher (IDEA / VS Code style).
|
|
2081
|
+
* Injected into the 'conversation.composer.dock' slot at order: -1.
|
|
2082
|
+
*/
|
|
2083
|
+
/**
|
|
2084
|
+
* Git Branch Pill rendered in the Composer Dock.
|
|
2085
|
+
*/
|
|
2086
|
+
const GitBranchPill = (0, react.memo)(function GitBranchPill({ getStatus, getBranches, checkout, pull, push, sessionId }) {
|
|
2087
|
+
const [status, setStatus] = (0, react.useState)(null);
|
|
2088
|
+
const [branches, setBranches] = (0, react.useState)(null);
|
|
2089
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
2090
|
+
const [filter, setFilter] = (0, react.useState)("");
|
|
2091
|
+
const [creatingBranch, setCreatingBranch] = (0, react.useState)(false);
|
|
2092
|
+
const [newBranchName, setNewBranchName] = (0, react.useState)("");
|
|
2093
|
+
const [switching, setSwitching] = (0, react.useState)(false);
|
|
2094
|
+
const anchorRef = (0, react.useRef)(null);
|
|
2095
|
+
const popoverRef = (0, react.useRef)(null);
|
|
2096
|
+
const [popoverPos, setPopoverPos] = (0, react.useState)(null);
|
|
2097
|
+
const refresh = (0, react.useCallback)(async () => {
|
|
2098
|
+
if (!getStatus || !getBranches) return;
|
|
2099
|
+
try {
|
|
2100
|
+
const [statusRes, branchRes] = await Promise.all([getStatus(sessionId), getBranches(sessionId)]);
|
|
2101
|
+
setStatus(statusRes);
|
|
2102
|
+
setBranches(branchRes);
|
|
2103
|
+
} catch {}
|
|
2104
|
+
}, [
|
|
2105
|
+
getStatus,
|
|
2106
|
+
getBranches,
|
|
2107
|
+
sessionId
|
|
2108
|
+
]);
|
|
2109
|
+
(0, react.useEffect)(() => {
|
|
2110
|
+
refresh();
|
|
2111
|
+
const timer = setInterval(() => {
|
|
2112
|
+
refresh();
|
|
2113
|
+
}, 5e3);
|
|
2114
|
+
return () => {
|
|
2115
|
+
clearInterval(timer);
|
|
2116
|
+
};
|
|
2117
|
+
}, [refresh]);
|
|
2118
|
+
const updatePosition = (0, react.useCallback)(() => {
|
|
2119
|
+
if (!anchorRef.current) return;
|
|
2120
|
+
const rect = anchorRef.current.getBoundingClientRect();
|
|
2121
|
+
setPopoverPos({
|
|
2122
|
+
bottom: window.innerHeight - rect.top + 6,
|
|
2123
|
+
left: Math.max(8, Math.min(rect.left, window.innerWidth - 330))
|
|
2124
|
+
});
|
|
2125
|
+
}, []);
|
|
2126
|
+
const handleToggle = (0, react.useCallback)((e) => {
|
|
2127
|
+
e.stopPropagation();
|
|
2128
|
+
if (!open) {
|
|
2129
|
+
updatePosition();
|
|
2130
|
+
refresh();
|
|
2131
|
+
}
|
|
2132
|
+
setOpen((prev) => !prev);
|
|
2133
|
+
setCreatingBranch(false);
|
|
2134
|
+
setFilter("");
|
|
2135
|
+
}, [
|
|
2136
|
+
open,
|
|
2137
|
+
refresh,
|
|
2138
|
+
updatePosition
|
|
2139
|
+
]);
|
|
2140
|
+
(0, react.useEffect)(() => {
|
|
2141
|
+
if (!open) return;
|
|
2142
|
+
const onPointerDown = (e) => {
|
|
2143
|
+
const target = e.target;
|
|
2144
|
+
if (popoverRef.current?.contains(target) || anchorRef.current?.contains(target)) return;
|
|
2145
|
+
setOpen(false);
|
|
2146
|
+
};
|
|
2147
|
+
const onKeyDown = (e) => {
|
|
2148
|
+
if (e.key === "Escape") setOpen(false);
|
|
2149
|
+
};
|
|
2150
|
+
document.addEventListener("pointerdown", onPointerDown);
|
|
2151
|
+
document.addEventListener("keydown", onKeyDown);
|
|
2152
|
+
return () => {
|
|
2153
|
+
document.removeEventListener("pointerdown", onPointerDown);
|
|
2154
|
+
document.removeEventListener("keydown", onKeyDown);
|
|
2155
|
+
};
|
|
2156
|
+
}, [open]);
|
|
2157
|
+
const handleCheckout = (0, react.useCallback)(async (branchName, create = false) => {
|
|
2158
|
+
if (!checkout || switching) return;
|
|
2159
|
+
setSwitching(true);
|
|
2160
|
+
try {
|
|
2161
|
+
const res = await checkout(sessionId, branchName, create);
|
|
2162
|
+
if (res.success) {
|
|
2163
|
+
setOpen(false);
|
|
2164
|
+
setCreatingBranch(false);
|
|
2165
|
+
setNewBranchName("");
|
|
2166
|
+
await refresh();
|
|
2167
|
+
} else alert(res.message ?? "Checkout failed");
|
|
2168
|
+
} finally {
|
|
2169
|
+
setSwitching(false);
|
|
2170
|
+
}
|
|
2171
|
+
}, [
|
|
2172
|
+
checkout,
|
|
2173
|
+
refresh,
|
|
2174
|
+
sessionId,
|
|
2175
|
+
switching
|
|
2176
|
+
]);
|
|
2177
|
+
const handleCreateBranchKeyDown = (0, react.useCallback)((e) => {
|
|
2178
|
+
if (e.key === "Enter") {
|
|
2179
|
+
const trimmed = newBranchName.trim();
|
|
2180
|
+
if (trimmed) handleCheckout(trimmed, true);
|
|
2181
|
+
} else if (e.key === "Escape") setCreatingBranch(false);
|
|
2182
|
+
}, [handleCheckout, newBranchName]);
|
|
2183
|
+
const handlePull = (0, react.useCallback)(async () => {
|
|
2184
|
+
if (!pull) return;
|
|
2185
|
+
await pull(sessionId);
|
|
2186
|
+
await refresh();
|
|
2187
|
+
}, [
|
|
2188
|
+
pull,
|
|
2189
|
+
refresh,
|
|
2190
|
+
sessionId
|
|
2191
|
+
]);
|
|
2192
|
+
const handlePush = (0, react.useCallback)(async () => {
|
|
2193
|
+
if (!push) return;
|
|
2194
|
+
await push(sessionId);
|
|
2195
|
+
await refresh();
|
|
2196
|
+
}, [
|
|
2197
|
+
push,
|
|
2198
|
+
refresh,
|
|
2199
|
+
sessionId
|
|
2200
|
+
]);
|
|
2201
|
+
const filteredLocal = (0, react.useMemo)(() => {
|
|
2202
|
+
if (!branches?.local) return [];
|
|
2203
|
+
const q = filter.trim().toLowerCase();
|
|
2204
|
+
return q ? branches.local.filter((b) => b.name.toLowerCase().includes(q)) : branches.local;
|
|
2205
|
+
}, [branches?.local, filter]);
|
|
2206
|
+
const filteredRemote = (0, react.useMemo)(() => {
|
|
2207
|
+
if (!branches?.remote) return [];
|
|
2208
|
+
const q = filter.trim().toLowerCase();
|
|
2209
|
+
return q ? branches.remote.filter((b) => b.name.toLowerCase().includes(q)) : branches.remote;
|
|
2210
|
+
}, [branches?.remote, filter]);
|
|
2211
|
+
if (status && !status.isRepo) return null;
|
|
2212
|
+
const currentBranchName = status?.branch || "master";
|
|
2213
|
+
return (0, react_jsx_runtime.jsxs)("span", {
|
|
2214
|
+
ref: anchorRef,
|
|
2215
|
+
className: GitBranchPill_module_css_default.anchor,
|
|
2216
|
+
"data-composer-stat": "git-branch",
|
|
2217
|
+
children: [(0, react_jsx_runtime.jsxs)("button", {
|
|
2218
|
+
type: "button",
|
|
2219
|
+
className: GitBranchPill_module_css_default.pill,
|
|
2220
|
+
"aria-haspopup": "dialog",
|
|
2221
|
+
"aria-expanded": open,
|
|
2222
|
+
title: `Git Branch: ${currentBranchName}`,
|
|
2223
|
+
onClick: handleToggle,
|
|
2224
|
+
children: [
|
|
2225
|
+
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBranchOutlineRegular, { className: GitBranchPill_module_css_default.icon }),
|
|
2226
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
2227
|
+
className: GitBranchPill_module_css_default.branchName,
|
|
2228
|
+
children: currentBranchName
|
|
2229
|
+
}),
|
|
2230
|
+
status !== null && status.ahead > 0 && (0, react_jsx_runtime.jsxs)("span", {
|
|
2231
|
+
className: `${GitBranchPill_module_css_default.badge} ${GitBranchPill_module_css_default.badgeAhead}`,
|
|
2232
|
+
children: ["↑", status.ahead]
|
|
2233
|
+
}),
|
|
2234
|
+
status !== null && status.behind > 0 && (0, react_jsx_runtime.jsxs)("span", {
|
|
2235
|
+
className: `${GitBranchPill_module_css_default.badge} ${GitBranchPill_module_css_default.badgeBehind}`,
|
|
2236
|
+
children: ["↓", status.behind]
|
|
2237
|
+
})
|
|
2238
|
+
]
|
|
2239
|
+
}), open && popoverPos && (0, react_dom.createPortal)((0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.MenuSurface, {
|
|
2240
|
+
ref: popoverRef,
|
|
2241
|
+
className: GitBranchPill_module_css_default.popover,
|
|
2242
|
+
style: {
|
|
2243
|
+
bottom: `${popoverPos.bottom}px`,
|
|
2244
|
+
left: `${popoverPos.left}px`
|
|
2245
|
+
},
|
|
2246
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
2247
|
+
className: GitBranchPill_module_css_default.header,
|
|
2248
|
+
children: [
|
|
2249
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
2250
|
+
className: GitBranchPill_module_css_default.searchRow,
|
|
2251
|
+
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutlineRegular, { className: GitBranchPill_module_css_default.searchIcon }), (0, react_jsx_runtime.jsx)("input", {
|
|
2252
|
+
autoFocus: true,
|
|
2253
|
+
className: GitBranchPill_module_css_default.searchInput,
|
|
2254
|
+
placeholder: "搜索或过滤分支...",
|
|
2255
|
+
value: filter,
|
|
2256
|
+
onChange: (e) => {
|
|
2257
|
+
setFilter(e.target.value);
|
|
2258
|
+
}
|
|
2259
|
+
})]
|
|
2260
|
+
}),
|
|
2261
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
2262
|
+
className: GitBranchPill_module_css_default.actionBar,
|
|
2263
|
+
children: [(0, react_jsx_runtime.jsxs)("button", {
|
|
2264
|
+
type: "button",
|
|
2265
|
+
className: GitBranchPill_module_css_default.toolBtn,
|
|
2266
|
+
title: "新建分支",
|
|
2267
|
+
onClick: () => {
|
|
2268
|
+
setCreatingBranch((prev) => !prev);
|
|
2269
|
+
},
|
|
2270
|
+
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutlineRegular, { className: GitBranchPill_module_css_default.btnIcon }), (0, react_jsx_runtime.jsx)("span", { children: "新建分支" })]
|
|
2271
|
+
}), (0, react_jsx_runtime.jsxs)("div", {
|
|
2272
|
+
className: GitBranchPill_module_css_default.toolBtnGroup,
|
|
2273
|
+
children: [
|
|
2274
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
2275
|
+
type: "button",
|
|
2276
|
+
className: GitBranchPill_module_css_default.toolBtn,
|
|
2277
|
+
title: "拉取 (Pull)",
|
|
2278
|
+
onClick: () => {
|
|
2279
|
+
handlePull();
|
|
2280
|
+
},
|
|
2281
|
+
children: "Pull"
|
|
2282
|
+
}),
|
|
2283
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
2284
|
+
type: "button",
|
|
2285
|
+
className: GitBranchPill_module_css_default.toolBtn,
|
|
2286
|
+
title: "推送 (Push)",
|
|
2287
|
+
onClick: () => {
|
|
2288
|
+
handlePush();
|
|
2289
|
+
},
|
|
2290
|
+
children: "Push"
|
|
2291
|
+
}),
|
|
2292
|
+
(0, react_jsx_runtime.jsx)("button", {
|
|
2293
|
+
type: "button",
|
|
2294
|
+
className: GitBranchPill_module_css_default.toolBtn,
|
|
2295
|
+
title: "刷新状态",
|
|
2296
|
+
onClick: () => {
|
|
2297
|
+
refresh();
|
|
2298
|
+
},
|
|
2299
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutlineRegular, { className: GitBranchPill_module_css_default.btnIcon })
|
|
2300
|
+
})
|
|
2301
|
+
]
|
|
2302
|
+
})]
|
|
2303
|
+
}),
|
|
2304
|
+
creatingBranch && (0, react_jsx_runtime.jsx)("div", {
|
|
2305
|
+
className: GitBranchPill_module_css_default.newBranchBox,
|
|
2306
|
+
children: (0, react_jsx_runtime.jsx)("input", {
|
|
2307
|
+
autoFocus: true,
|
|
2308
|
+
className: GitBranchPill_module_css_default.newBranchInput,
|
|
2309
|
+
placeholder: "新分支名称 (按 Enter 创建)...",
|
|
2310
|
+
value: newBranchName,
|
|
2311
|
+
onChange: (e) => {
|
|
2312
|
+
setNewBranchName(e.target.value);
|
|
2313
|
+
},
|
|
2314
|
+
onKeyDown: handleCreateBranchKeyDown
|
|
2315
|
+
})
|
|
2316
|
+
})
|
|
2317
|
+
]
|
|
2318
|
+
}), (0, react_jsx_runtime.jsxs)("div", {
|
|
2319
|
+
className: GitBranchPill_module_css_default.branchList,
|
|
2320
|
+
children: [
|
|
2321
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
2322
|
+
className: GitBranchPill_module_css_default.groupLabel,
|
|
2323
|
+
children: [
|
|
2324
|
+
"本地分支 (",
|
|
2325
|
+
filteredLocal.length,
|
|
2326
|
+
")"
|
|
2327
|
+
]
|
|
2328
|
+
}),
|
|
2329
|
+
filteredLocal.map((b) => (0, react_jsx_runtime.jsxs)("button", {
|
|
2330
|
+
type: "button",
|
|
2331
|
+
className: `${GitBranchPill_module_css_default.branchItem} ${b.isCurrent ? GitBranchPill_module_css_default.currentBranch : ""}`,
|
|
2332
|
+
disabled: switching,
|
|
2333
|
+
onClick: () => {
|
|
2334
|
+
if (!b.isCurrent) handleCheckout(b.name);
|
|
2335
|
+
},
|
|
2336
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
2337
|
+
className: GitBranchPill_module_css_default.branchItemLeft,
|
|
2338
|
+
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBranchOutlineRegular, { className: GitBranchPill_module_css_default.itemIcon }), (0, react_jsx_runtime.jsx)("span", {
|
|
2339
|
+
className: GitBranchPill_module_css_default.itemText,
|
|
2340
|
+
children: b.name
|
|
2341
|
+
})]
|
|
2342
|
+
}), b.isCurrent ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCheckOutlineRegular, { className: GitBranchPill_module_css_default.checkMark }) : b.ahead !== void 0 && b.ahead > 0 && (0, react_jsx_runtime.jsxs)("span", {
|
|
2343
|
+
className: GitBranchPill_module_css_default.badge,
|
|
2344
|
+
children: ["↑", b.ahead]
|
|
2345
|
+
})]
|
|
2346
|
+
}, b.name)),
|
|
2347
|
+
filteredRemote.length > 0 && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
2348
|
+
className: GitBranchPill_module_css_default.groupLabel,
|
|
2349
|
+
style: { marginTop: "6px" },
|
|
2350
|
+
children: [
|
|
2351
|
+
"远程分支 (",
|
|
2352
|
+
filteredRemote.length,
|
|
2353
|
+
")"
|
|
2354
|
+
]
|
|
2355
|
+
}), filteredRemote.map((b) => (0, react_jsx_runtime.jsx)("button", {
|
|
2356
|
+
type: "button",
|
|
2357
|
+
className: GitBranchPill_module_css_default.branchItem,
|
|
2358
|
+
disabled: switching,
|
|
2359
|
+
onClick: () => {
|
|
2360
|
+
handleCheckout(b.name);
|
|
2361
|
+
},
|
|
2362
|
+
children: (0, react_jsx_runtime.jsxs)("div", {
|
|
2363
|
+
className: GitBranchPill_module_css_default.branchItemLeft,
|
|
2364
|
+
children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBranchOutlineRegular, { className: GitBranchPill_module_css_default.itemIcon }), (0, react_jsx_runtime.jsx)("span", {
|
|
2365
|
+
className: GitBranchPill_module_css_default.itemText,
|
|
2366
|
+
children: b.name
|
|
2367
|
+
})]
|
|
2368
|
+
})
|
|
2369
|
+
}, b.name))] }),
|
|
2370
|
+
filteredLocal.length === 0 && filteredRemote.length === 0 && (0, react_jsx_runtime.jsx)("div", {
|
|
2371
|
+
className: GitBranchPill_module_css_default.emptyTip,
|
|
2372
|
+
children: "未找到匹配的分支"
|
|
2373
|
+
})
|
|
2374
|
+
]
|
|
2375
|
+
})]
|
|
2376
|
+
}), document.body)]
|
|
2377
|
+
});
|
|
2378
|
+
});
|
|
2379
|
+
//#endregion
|
|
2380
|
+
//#region lib/types/client/GitTitle.js
|
|
2381
|
+
/**
|
|
2382
|
+
* Git chip title component with branch glyph and title text.
|
|
2383
|
+
* @param props - Slot props including tab info hook.
|
|
2384
|
+
* @returns React node for tab chip.
|
|
2385
|
+
*/
|
|
2386
|
+
function GitTitle({ useTabInfo }) {
|
|
2387
|
+
const { tab } = useTabInfo();
|
|
2388
|
+
return (0, react_jsx_runtime.jsxs)("span", {
|
|
2389
|
+
className: GitBody_module_css_default.titleContainer,
|
|
2390
|
+
children: [(0, react_jsx_runtime.jsx)("svg", {
|
|
2391
|
+
className: GitBody_module_css_default.titleIcon,
|
|
2392
|
+
width: "14",
|
|
2393
|
+
height: "14",
|
|
2394
|
+
viewBox: "0 0 16 16",
|
|
2395
|
+
fill: "currentColor",
|
|
2396
|
+
children: (0, react_jsx_runtime.jsx)("path", { d: "M11.75 2.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5zm-2.25.75a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.492 2.492 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628A2.25 2.25 0 0 1 9.5 3.25zM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5zM3.5 3.25a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0z" })
|
|
2397
|
+
}), (0, react_jsx_runtime.jsx)("span", {
|
|
2398
|
+
className: GitBody_module_css_default.titleText,
|
|
2399
|
+
children: tab.title
|
|
2400
|
+
})]
|
|
2401
|
+
});
|
|
2402
|
+
}
|
|
2403
|
+
//#endregion
|
|
2404
|
+
//#region lib/types/client/locales.js
|
|
2405
|
+
/**
|
|
2406
|
+
* Localized copy for the Git right-sidebar viewer and commands.
|
|
2407
|
+
*/
|
|
2408
|
+
const NS = "gitView";
|
|
2409
|
+
const zh = {
|
|
2410
|
+
"type.label": "Git",
|
|
2411
|
+
"guide.title": "Git 版本控制",
|
|
2412
|
+
"guide.description": "查看项目代码变更、分支、提交历史与差异对比",
|
|
2413
|
+
"shortcut.noSession": "没有激活的会话",
|
|
2414
|
+
"tabs.changes": "更改",
|
|
2415
|
+
"tabs.history": "提交历史",
|
|
2416
|
+
"tabs.tree": "提交图谱树",
|
|
2417
|
+
"tabs.branches": "分支管理",
|
|
2418
|
+
"tabs.tags": "标签管理",
|
|
2419
|
+
"actions.refresh": "刷新状态",
|
|
2420
|
+
"actions.viewDiff": "查看差异",
|
|
2421
|
+
"actions.closeDiff": "收起差异",
|
|
2422
|
+
"actions.stage": "暂存",
|
|
2423
|
+
"actions.unstage": "取消暂存",
|
|
2424
|
+
"actions.stageAll": "全部暂存",
|
|
2425
|
+
"actions.unstageAll": "全部取消暂存",
|
|
2426
|
+
"actions.discard": "放弃更改",
|
|
2427
|
+
"actions.commit": "提交",
|
|
2428
|
+
"actions.commitAndPush": "提交并推送",
|
|
2429
|
+
"actions.checkout": "检出分支",
|
|
2430
|
+
"actions.newBranch": "新建分支",
|
|
2431
|
+
"actions.fetch": "获取远程",
|
|
2432
|
+
"actions.pull": "拉取",
|
|
2433
|
+
"actions.push": "推送",
|
|
2434
|
+
"commit.placeholder": "输入提交信息 (Ctrl+Enter 提交)...",
|
|
2435
|
+
"commit.emptyWarning": "请输入提交说明",
|
|
2436
|
+
"commit.success": "提交成功",
|
|
2437
|
+
"branch.filter": "搜索过滤分支...",
|
|
2438
|
+
"branch.local": "本地分支",
|
|
2439
|
+
"branch.remote": "远程分支",
|
|
2440
|
+
"branch.current": "当前分支",
|
|
2441
|
+
"branch.newPrompt": "输入新分支名称...",
|
|
2442
|
+
"branch.createAndCheckout": "创建并检出",
|
|
2443
|
+
"tree.author": "作者",
|
|
2444
|
+
"tree.date": "时间",
|
|
2445
|
+
"tree.hash": "哈希",
|
|
2446
|
+
"tree.changedFiles": "变更文件",
|
|
2447
|
+
"tree.selectCommit": "点击任意提交查看详情与代码差异",
|
|
2448
|
+
"status.clean": "工作树干净,无任何未提交更改",
|
|
2449
|
+
"status.notRepo": "当前工作区不是 Git 仓库",
|
|
2450
|
+
"status.staged": "已暂存更改",
|
|
2451
|
+
"status.unstaged": "工作区修改",
|
|
2452
|
+
"status.untracked": "未跟踪文件",
|
|
2453
|
+
"status.ahead": "领先 {count} 个提交",
|
|
2454
|
+
"status.behind": "落后 {count} 个提交",
|
|
2455
|
+
"diff.additions": "+{count}",
|
|
2456
|
+
"diff.deletions": "-{count}",
|
|
2457
|
+
"diff.empty": "无内容变动",
|
|
2458
|
+
"tag.filter": "搜索过滤标签 (名称、Hash、提交说明)...",
|
|
2459
|
+
"tag.newPrompt": "新建标签 (Tag)",
|
|
2460
|
+
"tag.nameLabel": "标签名称",
|
|
2461
|
+
"tag.namePlaceholder": "输入标签名称 (例如 v1.0.0)...",
|
|
2462
|
+
"tag.targetCommitLabel": "目标 Commit Hash (可选,留空为 HEAD)",
|
|
2463
|
+
"tag.messageLabel": "说明信息 (可选附注内容)",
|
|
2464
|
+
"tag.messagePrompt": "输入附注说明信息 (可选)...",
|
|
2465
|
+
"tag.createBtn": "创建标签",
|
|
2466
|
+
"tag.cancelBtn": "取消",
|
|
2467
|
+
"tag.locateBtn": "在图谱中定位",
|
|
2468
|
+
"tag.copyName": "复制标签名",
|
|
2469
|
+
"tag.deleteBtn": "删除",
|
|
2470
|
+
"tag.deleteConfirm": "确定要删除标签 \"{name}\" 吗?",
|
|
2471
|
+
"tag.empty": "暂无任何 Git 标签",
|
|
2472
|
+
"tag.annotated": "附注",
|
|
2473
|
+
"tag.locatedNotice": "已定位到标签 \"{name}\" 所在的提交",
|
|
2474
|
+
"actions.locate": "定位",
|
|
2475
|
+
"tree.colGraph": "图谱",
|
|
2476
|
+
"tree.colSubject": "提交说明与分支标记",
|
|
2477
|
+
"tree.colAuthor": "作者",
|
|
2478
|
+
"tree.colTime": "时间",
|
|
2479
|
+
"tree.colSha": "Commit SHA",
|
|
2480
|
+
"tree.searchPlaceholder": "搜索提交说明、SHA 或作者...",
|
|
2481
|
+
"tree.filterAll": "全部",
|
|
2482
|
+
"tree.filterMainline": "仅主线",
|
|
2483
|
+
"detail.title": "提交详情 (COMMIT DETAILS)",
|
|
2484
|
+
"detail.references": "包含引用 (REFERENCES)",
|
|
2485
|
+
"detail.author": "作者 (Author)",
|
|
2486
|
+
"detail.date": "提交时间 (Date)",
|
|
2487
|
+
"detail.parent": "父级提交 (Parent)",
|
|
2488
|
+
"detail.checkout": "检出分支 (Checkout)",
|
|
2489
|
+
"detail.createBranchOrTag": "创建分支 / 标签",
|
|
2490
|
+
"footer.showingCount": "已显示 {count} 条提交 (共 {total} 条)",
|
|
2491
|
+
"footer.loadMore": "加载更多",
|
|
2492
|
+
"footer.syncNormal": "分支同步正常",
|
|
2493
|
+
"footer.ahead": "本地领先 {count} 个提交",
|
|
2494
|
+
"footer.behind": "落后远程 {count} 个提交"
|
|
2495
|
+
};
|
|
2496
|
+
const en = {
|
|
2497
|
+
"type.label": "Git",
|
|
2498
|
+
"guide.title": "Git Source Control",
|
|
2499
|
+
"guide.description": "View project code changes, branches, commit log, and unified diffs",
|
|
2500
|
+
"shortcut.noSession": "No active session",
|
|
2501
|
+
"tabs.changes": "Changes",
|
|
2502
|
+
"tabs.history": "History",
|
|
2503
|
+
"tabs.tree": "Git Tree & Log",
|
|
2504
|
+
"tabs.branches": "Branches",
|
|
2505
|
+
"tabs.tags": "Tags",
|
|
2506
|
+
"actions.refresh": "Refresh status",
|
|
2507
|
+
"actions.viewDiff": "View Diff",
|
|
2508
|
+
"actions.closeDiff": "Collapse Diff",
|
|
2509
|
+
"actions.stage": "Stage",
|
|
2510
|
+
"actions.unstage": "Unstage",
|
|
2511
|
+
"actions.stageAll": "Stage All",
|
|
2512
|
+
"actions.unstageAll": "Unstage All",
|
|
2513
|
+
"actions.discard": "Discard",
|
|
2514
|
+
"actions.commit": "Commit",
|
|
2515
|
+
"actions.commitAndPush": "Commit and Push",
|
|
2516
|
+
"actions.checkout": "Checkout",
|
|
2517
|
+
"actions.newBranch": "New Branch",
|
|
2518
|
+
"actions.fetch": "Fetch",
|
|
2519
|
+
"actions.pull": "Pull",
|
|
2520
|
+
"actions.push": "Push",
|
|
2521
|
+
"commit.placeholder": "Commit message (Ctrl+Enter to commit)...",
|
|
2522
|
+
"commit.emptyWarning": "Please enter a commit message",
|
|
2523
|
+
"commit.success": "Committed successfully",
|
|
2524
|
+
"branch.filter": "Filter branches...",
|
|
2525
|
+
"branch.local": "Local Branches",
|
|
2526
|
+
"branch.remote": "Remote Branches",
|
|
2527
|
+
"branch.current": "Current Branch",
|
|
2528
|
+
"branch.newPrompt": "Enter new branch name...",
|
|
2529
|
+
"branch.createAndCheckout": "Create & Checkout",
|
|
2530
|
+
"tree.author": "Author",
|
|
2531
|
+
"tree.date": "Date",
|
|
2532
|
+
"tree.hash": "Hash",
|
|
2533
|
+
"tree.changedFiles": "Changed Files",
|
|
2534
|
+
"tree.selectCommit": "Select a commit to view details and code diff",
|
|
2535
|
+
"status.clean": "Working tree clean, no uncommitted changes",
|
|
2536
|
+
"status.notRepo": "Current workspace is not a Git repository",
|
|
2537
|
+
"status.staged": "Staged Changes",
|
|
2538
|
+
"status.unstaged": "Unstaged Changes",
|
|
2539
|
+
"status.untracked": "Untracked Files",
|
|
2540
|
+
"status.ahead": "{count} ahead",
|
|
2541
|
+
"status.behind": "{count} behind",
|
|
2542
|
+
"diff.additions": "+{count}",
|
|
2543
|
+
"diff.deletions": "-{count}",
|
|
2544
|
+
"diff.empty": "No content changes",
|
|
2545
|
+
"tag.filter": "Filter tags (name, hash, message)...",
|
|
2546
|
+
"tag.newPrompt": "New Tag",
|
|
2547
|
+
"tag.nameLabel": "Tag Name",
|
|
2548
|
+
"tag.namePlaceholder": "Enter tag name (e.g. v1.0.0)...",
|
|
2549
|
+
"tag.targetCommitLabel": "Target Commit Hash (optional, defaults to HEAD)",
|
|
2550
|
+
"tag.messageLabel": "Message (optional annotation)",
|
|
2551
|
+
"tag.messagePrompt": "Enter annotation message (optional)...",
|
|
2552
|
+
"tag.createBtn": "Create Tag",
|
|
2553
|
+
"tag.cancelBtn": "Cancel",
|
|
2554
|
+
"tag.locateBtn": "Locate in Graph",
|
|
2555
|
+
"tag.copyName": "Copy Tag Name",
|
|
2556
|
+
"tag.deleteBtn": "Delete",
|
|
2557
|
+
"tag.deleteConfirm": "Are you sure you want to delete tag \"{name}\"?",
|
|
2558
|
+
"tag.empty": "No Git tags found",
|
|
2559
|
+
"tag.annotated": "Annotated",
|
|
2560
|
+
"tag.locatedNotice": "Located commit for tag \"{name}\"",
|
|
2561
|
+
"actions.locate": "Locate",
|
|
2562
|
+
"tree.colGraph": "Graph",
|
|
2563
|
+
"tree.colSubject": "Commit Subject & References",
|
|
2564
|
+
"tree.colAuthor": "Author",
|
|
2565
|
+
"tree.colTime": "Time",
|
|
2566
|
+
"tree.colSha": "Commit SHA",
|
|
2567
|
+
"tree.searchPlaceholder": "Search subject, SHA or author...",
|
|
2568
|
+
"tree.filterAll": "All",
|
|
2569
|
+
"tree.filterMainline": "Mainline",
|
|
2570
|
+
"detail.title": "COMMIT DETAILS",
|
|
2571
|
+
"detail.references": "REFERENCES",
|
|
2572
|
+
"detail.author": "Author",
|
|
2573
|
+
"detail.date": "Date",
|
|
2574
|
+
"detail.parent": "Parent",
|
|
2575
|
+
"detail.checkout": "Checkout",
|
|
2576
|
+
"detail.createBranchOrTag": "Create Branch / Tag",
|
|
2577
|
+
"footer.showingCount": "Showing {count} commits (total {total})",
|
|
2578
|
+
"footer.loadMore": "Load more",
|
|
2579
|
+
"footer.syncNormal": "Branch in sync",
|
|
2580
|
+
"footer.ahead": "{count} ahead of remote",
|
|
2581
|
+
"footer.behind": "{count} behind remote"
|
|
2582
|
+
};
|
|
2583
|
+
//#endregion
|
|
2584
|
+
//#region lib/types/client/index.js
|
|
2585
|
+
/**
|
|
2586
|
+
* Browser entry for the experimental Git right-sidebar plugin.
|
|
2587
|
+
*/
|
|
2588
|
+
/**
|
|
2589
|
+
* Required browser services.
|
|
2590
|
+
*/
|
|
2591
|
+
const inject = [
|
|
2592
|
+
"connection",
|
|
2593
|
+
"slots",
|
|
2594
|
+
"locale",
|
|
2595
|
+
"sidebarRightTabs",
|
|
2596
|
+
"sidebarRight"
|
|
2597
|
+
];
|
|
2598
|
+
/**
|
|
2599
|
+
* Client plugin body: registers Git tab definition, locales, shortcut, and components.
|
|
2600
|
+
* @param ctx - Client context carrying slots and connection services.
|
|
2601
|
+
*/
|
|
2602
|
+
function apply(ctx) {
|
|
2603
|
+
const t = ctx.locale.bind(NS);
|
|
2604
|
+
ctx.effect(() => ctx.locale.register(NS, {
|
|
2605
|
+
zh,
|
|
2606
|
+
en
|
|
2607
|
+
}), "experimental-git: locales");
|
|
2608
|
+
ctx.effect(() => ctx.sidebarRightTabs.register(gitDefinition(t)), "experimental-git: tab definition");
|
|
2609
|
+
ctx.inject(["shortcuts"], (scope) => {
|
|
2610
|
+
scope.effect(() => scope.shortcuts.register({
|
|
2611
|
+
id: "workspace.git",
|
|
2612
|
+
label: () => t("guide.title"),
|
|
2613
|
+
aliases: [
|
|
2614
|
+
"workspace git",
|
|
2615
|
+
"git",
|
|
2616
|
+
"source control"
|
|
2617
|
+
],
|
|
2618
|
+
defaults: {
|
|
2619
|
+
"desktop:macos": {
|
|
2620
|
+
code: "KeyG",
|
|
2621
|
+
modifiers: ["primary", "shift"]
|
|
2622
|
+
},
|
|
2623
|
+
"desktop:windows": {
|
|
2624
|
+
code: "KeyG",
|
|
2625
|
+
modifiers: ["primary", "shift"]
|
|
2626
|
+
},
|
|
2627
|
+
"desktop:linux": {
|
|
2628
|
+
code: "KeyG",
|
|
2629
|
+
modifiers: ["primary", "shift"]
|
|
2630
|
+
},
|
|
2631
|
+
"web:macos": {
|
|
2632
|
+
code: "KeyG",
|
|
2633
|
+
modifiers: ["primary", "shift"]
|
|
2634
|
+
},
|
|
2635
|
+
"web:windows": {
|
|
2636
|
+
code: "KeyG",
|
|
2637
|
+
modifiers: ["primary", "shift"]
|
|
2638
|
+
}
|
|
2639
|
+
},
|
|
2640
|
+
regions: [
|
|
2641
|
+
"page",
|
|
2642
|
+
"editable",
|
|
2643
|
+
"terminal"
|
|
2644
|
+
],
|
|
2645
|
+
modals: [],
|
|
2646
|
+
resolve: ({ target: element }) => {
|
|
2647
|
+
const target = scope.sidebarRight.commandTarget(element);
|
|
2648
|
+
if (target === void 0) return {
|
|
2649
|
+
status: "blocked",
|
|
2650
|
+
reason: t("shortcut.noSession")
|
|
2651
|
+
};
|
|
2652
|
+
return {
|
|
2653
|
+
status: "handled",
|
|
2654
|
+
run: () => {
|
|
2655
|
+
scope.sidebarRight.openTabFromTarget("git", target);
|
|
2656
|
+
}
|
|
2657
|
+
};
|
|
2658
|
+
}
|
|
2659
|
+
}), "experimental-git: shortcut");
|
|
2660
|
+
});
|
|
2661
|
+
const getConnection = () => {
|
|
2662
|
+
const handle = ctx.get("connection");
|
|
2663
|
+
if (!handle) throw new Error("Connection service not available");
|
|
2664
|
+
return handle;
|
|
2665
|
+
};
|
|
2666
|
+
const actions = {
|
|
2667
|
+
getStatus: async (sessionId) => {
|
|
2668
|
+
const res = await getConnection().rpc.call("/git", "status", { sessionId });
|
|
2669
|
+
if (!res.ok) throw new Error(res.error.message);
|
|
2670
|
+
return res.value;
|
|
2671
|
+
},
|
|
2672
|
+
getLog: async (sessionId, maxCount) => {
|
|
2673
|
+
const res = await getConnection().rpc.call("/git", "log", {
|
|
2674
|
+
sessionId,
|
|
2675
|
+
maxCount
|
|
2676
|
+
});
|
|
2677
|
+
if (!res.ok) throw new Error(res.error.message);
|
|
2678
|
+
return res.value;
|
|
2679
|
+
},
|
|
2680
|
+
getCommitDetails: async (sessionId, commit) => {
|
|
2681
|
+
const res = await getConnection().rpc.call("/git", "commitDetails", {
|
|
2682
|
+
sessionId,
|
|
2683
|
+
commit
|
|
2684
|
+
});
|
|
2685
|
+
if (!res.ok) throw new Error(res.error.message);
|
|
2686
|
+
return res.value;
|
|
2687
|
+
},
|
|
2688
|
+
getDiff: async (sessionId, options) => {
|
|
2689
|
+
const res = await getConnection().rpc.call("/git", "diff", {
|
|
2690
|
+
sessionId,
|
|
2691
|
+
...options
|
|
2692
|
+
});
|
|
2693
|
+
if (!res.ok) throw new Error(res.error.message);
|
|
2694
|
+
return res.value;
|
|
2695
|
+
},
|
|
2696
|
+
getBranches: async (sessionId) => {
|
|
2697
|
+
const res = await getConnection().rpc.call("/git", "branches", { sessionId });
|
|
2698
|
+
if (!res.ok) throw new Error(res.error.message);
|
|
2699
|
+
return res.value;
|
|
2700
|
+
},
|
|
2701
|
+
checkout: async (sessionId, branch, create) => {
|
|
2702
|
+
const res = await getConnection().rpc.call("/git", "checkout", {
|
|
2703
|
+
sessionId,
|
|
2704
|
+
branch,
|
|
2705
|
+
create
|
|
2706
|
+
});
|
|
2707
|
+
if (!res.ok) return {
|
|
2708
|
+
success: false,
|
|
2709
|
+
message: res.error.message
|
|
2710
|
+
};
|
|
2711
|
+
return res.value;
|
|
2712
|
+
},
|
|
2713
|
+
stage: async (sessionId, paths) => {
|
|
2714
|
+
const res = await getConnection().rpc.call("/git", "stage", {
|
|
2715
|
+
sessionId,
|
|
2716
|
+
paths
|
|
2717
|
+
});
|
|
2718
|
+
if (!res.ok) return {
|
|
2719
|
+
success: false,
|
|
2720
|
+
message: res.error.message
|
|
2721
|
+
};
|
|
2722
|
+
return res.value;
|
|
2723
|
+
},
|
|
2724
|
+
unstage: async (sessionId, paths) => {
|
|
2725
|
+
const res = await getConnection().rpc.call("/git", "unstage", {
|
|
2726
|
+
sessionId,
|
|
2727
|
+
paths
|
|
2728
|
+
});
|
|
2729
|
+
if (!res.ok) return {
|
|
2730
|
+
success: false,
|
|
2731
|
+
message: res.error.message
|
|
2732
|
+
};
|
|
2733
|
+
return res.value;
|
|
2734
|
+
},
|
|
2735
|
+
discard: async (sessionId, paths) => {
|
|
2736
|
+
const res = await getConnection().rpc.call("/git", "discard", {
|
|
2737
|
+
sessionId,
|
|
2738
|
+
paths
|
|
2739
|
+
});
|
|
2740
|
+
if (!res.ok) return {
|
|
2741
|
+
success: false,
|
|
2742
|
+
message: res.error.message
|
|
2743
|
+
};
|
|
2744
|
+
return res.value;
|
|
2745
|
+
},
|
|
2746
|
+
commit: async (sessionId, message) => {
|
|
2747
|
+
const res = await getConnection().rpc.call("/git", "commit", {
|
|
2748
|
+
sessionId,
|
|
2749
|
+
message
|
|
2750
|
+
});
|
|
2751
|
+
if (!res.ok) return {
|
|
2752
|
+
success: false,
|
|
2753
|
+
message: res.error.message
|
|
2754
|
+
};
|
|
2755
|
+
return res.value;
|
|
2756
|
+
},
|
|
2757
|
+
fetch: async (sessionId) => {
|
|
2758
|
+
const res = await getConnection().rpc.call("/git", "fetch", { sessionId });
|
|
2759
|
+
if (!res.ok) return {
|
|
2760
|
+
success: false,
|
|
2761
|
+
message: res.error.message
|
|
2762
|
+
};
|
|
2763
|
+
return res.value;
|
|
2764
|
+
},
|
|
2765
|
+
pull: async (sessionId) => {
|
|
2766
|
+
const res = await getConnection().rpc.call("/git", "pull", { sessionId });
|
|
2767
|
+
if (!res.ok) return {
|
|
2768
|
+
success: false,
|
|
2769
|
+
message: res.error.message
|
|
2770
|
+
};
|
|
2771
|
+
return res.value;
|
|
2772
|
+
},
|
|
2773
|
+
push: async (sessionId) => {
|
|
2774
|
+
const res = await getConnection().rpc.call("/git", "push", { sessionId });
|
|
2775
|
+
if (!res.ok) return {
|
|
2776
|
+
success: false,
|
|
2777
|
+
message: res.error.message
|
|
2778
|
+
};
|
|
2779
|
+
return res.value;
|
|
2780
|
+
},
|
|
2781
|
+
getTags: async (sessionId) => {
|
|
2782
|
+
const res = await getConnection().rpc.call("/git", "tags", { sessionId });
|
|
2783
|
+
if (!res.ok) throw new Error(res.error.message);
|
|
2784
|
+
return res.value;
|
|
2785
|
+
},
|
|
2786
|
+
createTag: async (sessionId, name, commit, message) => {
|
|
2787
|
+
const res = await getConnection().rpc.call("/git", "createTag", {
|
|
2788
|
+
sessionId,
|
|
2789
|
+
name,
|
|
2790
|
+
commit,
|
|
2791
|
+
message
|
|
2792
|
+
});
|
|
2793
|
+
if (!res.ok) return {
|
|
2794
|
+
success: false,
|
|
2795
|
+
message: res.error.message
|
|
2796
|
+
};
|
|
2797
|
+
return res.value;
|
|
2798
|
+
},
|
|
2799
|
+
deleteTag: async (sessionId, name) => {
|
|
2800
|
+
const res = await getConnection().rpc.call("/git", "deleteTag", {
|
|
2801
|
+
sessionId,
|
|
2802
|
+
name
|
|
2803
|
+
});
|
|
2804
|
+
if (!res.ok) return {
|
|
2805
|
+
success: false,
|
|
2806
|
+
message: res.error.message
|
|
2807
|
+
};
|
|
2808
|
+
return res.value;
|
|
2809
|
+
}
|
|
2810
|
+
};
|
|
2811
|
+
ctx.effect(() => ctx.slots.inject("sidebar.right.pane.tab", () => ctx.slots.register({
|
|
2812
|
+
name: "sidebar.right.pane.tab",
|
|
2813
|
+
key: GIT_ID,
|
|
2814
|
+
locale: NS,
|
|
2815
|
+
inject: () => actions
|
|
2816
|
+
}, GitBody)), "experimental-git: tab body");
|
|
2817
|
+
ctx.effect(() => ctx.slots.inject("sidebar.right.pane.tab.title", () => ctx.slots.register({
|
|
2818
|
+
name: "sidebar.right.pane.tab.title",
|
|
2819
|
+
key: GIT_ID
|
|
2820
|
+
}, GitTitle)), "experimental-git: tab title");
|
|
2821
|
+
ctx.slots.inject("conversation.composer.dock", () => ctx.slots.register({
|
|
2822
|
+
name: "conversation.composer.dock",
|
|
2823
|
+
id: "git-branch",
|
|
2824
|
+
order: -1,
|
|
2825
|
+
locale: NS,
|
|
2826
|
+
inject: () => actions
|
|
2827
|
+
}, GitBranchPill));
|
|
2828
|
+
}
|
|
2829
|
+
//#endregion
|
|
2830
|
+
exports.apply = apply;
|
|
2831
|
+
exports.inject = inject;
|
|
2832
|
+
return module.exports;
|
|
2833
|
+
}
|
|
2834
|
+
});
|
|
2835
|
+
|
|
2836
|
+
//# sourceMappingURL=client.js.map
|