@youtyan/code-viewer 0.12.0 → 0.13.1
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/README.md +14 -0
- package/dist/code-viewer.js +1515 -246
- package/package.json +1 -1
- package/web/app.js +2328 -349
- package/web/index.html +5 -0
- package/web/style.css +335 -39
package/web/app.js
CHANGED
|
@@ -875,6 +875,17 @@ Details: ${JSON.stringify(output)}` : "";
|
|
|
875
875
|
};
|
|
876
876
|
}
|
|
877
877
|
|
|
878
|
+
// web-src/core/file-refresh.ts
|
|
879
|
+
function rawFileInfoSignature(info) {
|
|
880
|
+
if (info.missing) return "missing";
|
|
881
|
+
if (info.size == null && !info.updated_at && !info.commit_updated_at)
|
|
882
|
+
return null;
|
|
883
|
+
return `${info.size ?? ""}|${info.updated_at ?? ""}|${info.commit_updated_at ?? ""}`;
|
|
884
|
+
}
|
|
885
|
+
function fileSignatureUnchanged(stored, key, sig) {
|
|
886
|
+
return stored !== null && stored.key === key && stored.sig === sig;
|
|
887
|
+
}
|
|
888
|
+
|
|
878
889
|
// web-src/core/focus-scope.ts
|
|
879
890
|
function isEditableKeyTarget(target) {
|
|
880
891
|
if (!target) return false;
|
|
@@ -1119,6 +1130,7 @@ Details: ${JSON.stringify(output)}` : "";
|
|
|
1119
1130
|
var PENCIL_16_PATH = "M11.013 1.427a1.75 1.75 0 0 1 2.474 0l1.086 1.086a1.75 1.75 0 0 1 0 2.474l-8.61 8.61c-.21.21-.47.364-.756.445l-3.251.93a.75.75 0 0 1-.927-.928l.929-3.25c.081-.286.235-.547.445-.758l8.61-8.609Zm.176 4.823L9.75 4.81l-6.286 6.287a.253.253 0 0 0-.064.108l-.558 1.953 1.953-.558a.253.253 0 0 0 .108-.064Zm1.238-3.763a.25.25 0 0 0-.354 0L10.811 3.75l1.439 1.44 1.263-1.263a.25.25 0 0 0 0-.354Z";
|
|
1120
1131
|
var COMMENT_DISCUSSION_16_PATH = "M1.75 1h8.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 10.25 10H7.061l-2.574 2.573A1.458 1.458 0 0 1 2 11.543V10h-.25A1.75 1.75 0 0 1 0 8.25v-5.5C0 1.784.784 1 1.75 1ZM1.5 2.75v5.5c0 .138.112.25.25.25h1a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h3.5a.25.25 0 0 0 .25-.25v-5.5a.25.25 0 0 0-.25-.25h-8.5a.25.25 0 0 0-.25.25Zm13 2a.25.25 0 0 0-.25-.25h-.5a.75.75 0 0 1 0-1.5h.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 14.25 12H14v1.543a1.458 1.458 0 0 1-2.487 1.03L9.22 12.28a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l2.22 2.22v-2.19a.75.75 0 0 1 .75-.75h1a.25.25 0 0 0 .25-.25Z";
|
|
1121
1132
|
var GRABBER_16_PATH = "M10 13h4v-2h-4v2Zm-8 0h4v-2H2v2Zm8-6h4V5h-4v2ZM2 7h4V5H2v2Zm8-6v2h4V1h-4ZM2 3h4V1H2v2Z";
|
|
1133
|
+
var KEBAB_16_PATH = "M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z";
|
|
1122
1134
|
var PULSE_16_PATH = "M6 2c.306 0 .582.187.696.471L10 10.731l1.304-3.26A.751.751 0 0 1 12 7h3.25a.75.75 0 0 1 0 1.5h-2.742l-1.812 4.528a.751.751 0 0 1-1.392 0L6 4.77 4.696 8.03A.75.75 0 0 1 4 8.5H.75a.75.75 0 0 1 0-1.5h2.742l1.812-4.529A.751.751 0 0 1 6 2Z";
|
|
1123
1135
|
var MOON_16_PATH = "M9.598 1.591a.749.749 0 0 1 .785-.175 7.001 7.001 0 1 1-8.967 8.967.75.75 0 0 1 .961-.96 5.5 5.5 0 0 0 7.046-7.046.75.75 0 0 1 .175-.786Zm1.616 1.945a7 7 0 0 1-7.678 7.678 5.499 5.499 0 1 0 7.678-7.678Z";
|
|
1124
1136
|
var QUESTION_16_PATH = "M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.92 6.085h.001a.749.749 0 1 1-1.342-.67c.169-.339.436-.701.849-.977C6.845 4.16 7.369 4 8 4a2.756 2.756 0 0 1 1.637.525c.503.377.863.965.863 1.725 0 .448-.115.83-.329 1.15-.205.307-.47.513-.692.662-.109.072-.22.138-.313.195l-.006.004a6.24 6.24 0 0 0-.26.16.952.952 0 0 0-.276.245.75.75 0 0 1-1.248-.832c.184-.264.42-.489.692-.661.103-.067.207-.132.313-.195l.007-.004c.1-.061.182-.11.258-.161a.969.969 0 0 0 .277-.245C8.96 6.514 9 6.427 9 6.25a.612.612 0 0 0-.262-.525A1.27 1.27 0 0 0 8 5.5c-.369 0-.595.09-.74.187a1.01 1.01 0 0 0-.34.398ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z";
|
|
@@ -1795,6 +1807,19 @@ Details: ${JSON.stringify(output)}` : "";
|
|
|
1795
1807
|
lang: params.get("lang") || "en",
|
|
1796
1808
|
section: params.get("section") || "overview"
|
|
1797
1809
|
};
|
|
1810
|
+
case "/worktree": {
|
|
1811
|
+
const wt = params.get("wt") || "";
|
|
1812
|
+
const file = params.get("file") || "";
|
|
1813
|
+
const rawOrigin = params.get("origin");
|
|
1814
|
+
const origin = rawOrigin === "committed" || rawOrigin === "uncommitted" ? rawOrigin : void 0;
|
|
1815
|
+
return {
|
|
1816
|
+
screen: "worktree",
|
|
1817
|
+
...wt ? { wt } : {},
|
|
1818
|
+
...file ? { file } : {},
|
|
1819
|
+
...origin ? { origin } : {},
|
|
1820
|
+
range
|
|
1821
|
+
};
|
|
1822
|
+
}
|
|
1798
1823
|
case "/doctor":
|
|
1799
1824
|
return {
|
|
1800
1825
|
screen: "repo",
|
|
@@ -1878,6 +1903,14 @@ Details: ${JSON.stringify(output)}` : "";
|
|
|
1878
1903
|
return "/file?path=" + encodeURIComponent(route.path) + "&ref=" + encodeURIComponent(route.ref || "worktree") + "&from=" + encodeURIComponent(route.range.from || "") + "&to=" + encodeURIComponent(route.range.to || "worktree") + (route.line ? `&line=${encodeURIComponent(formatLineTarget(route.line))}` : "") + (route.virtual === "off" ? "&virtual=off" : "");
|
|
1879
1904
|
case "diff":
|
|
1880
1905
|
return "/todif?from=" + encodeURIComponent(route.range.from || "") + "&to=" + encodeURIComponent(route.range.to || "worktree") + (route.path ? `&path=${encodeURIComponent(route.path)}` : "") + (route.line ? `&line=${encodeURIComponent(formatLineTarget(route.line))}` : "");
|
|
1906
|
+
case "worktree": {
|
|
1907
|
+
const params = new URLSearchParams();
|
|
1908
|
+
if (route.wt) params.set("wt", route.wt);
|
|
1909
|
+
if (route.file) params.set("file", route.file);
|
|
1910
|
+
if (route.file && route.origin) params.set("origin", route.origin);
|
|
1911
|
+
const qs = params.toString();
|
|
1912
|
+
return `/worktree${qs ? `?${qs}` : ""}`;
|
|
1913
|
+
}
|
|
1881
1914
|
case "help": {
|
|
1882
1915
|
const params = new URLSearchParams();
|
|
1883
1916
|
if (route.lang && route.lang !== "en") params.set("lang", route.lang);
|
|
@@ -1937,8 +1970,8 @@ Details: ${JSON.stringify(output)}` : "";
|
|
|
1937
1970
|
const qs = params.toString();
|
|
1938
1971
|
return qs ? `${base2}?${qs}` : base2;
|
|
1939
1972
|
}
|
|
1940
|
-
function withDoctorOverlay(url,
|
|
1941
|
-
return withQueryParam(url, "doctor",
|
|
1973
|
+
function withDoctorOverlay(url, open2) {
|
|
1974
|
+
return withQueryParam(url, "doctor", open2 ? "open" : null);
|
|
1942
1975
|
}
|
|
1943
1976
|
function parseToolsOverlay(search) {
|
|
1944
1977
|
const raw = new URLSearchParams(search).get("tools");
|
|
@@ -7924,8 +7957,8 @@ Details: ${JSON.stringify(output)}` : "";
|
|
|
7924
7957
|
compile(this);
|
|
7925
7958
|
return this;
|
|
7926
7959
|
}
|
|
7927
|
-
this.__tlds__ = this.__tlds__.concat(list2).sort().filter(function(
|
|
7928
|
-
return
|
|
7960
|
+
this.__tlds__ = this.__tlds__.concat(list2).sort().filter(function(el2, idx, arr) {
|
|
7961
|
+
return el2 !== arr[idx - 1];
|
|
7929
7962
|
}).reverse();
|
|
7930
7963
|
compile(this);
|
|
7931
7964
|
return this;
|
|
@@ -9165,8 +9198,8 @@ Details: ${JSON.stringify(output)}` : "";
|
|
|
9165
9198
|
const markerRe = new RegExp(`^\\[!(${ALERT_TYPES.join("|")})\\]\\s*`, "i");
|
|
9166
9199
|
let i2 = 0;
|
|
9167
9200
|
while (i2 < state.tokens.length) {
|
|
9168
|
-
const
|
|
9169
|
-
if (
|
|
9201
|
+
const open2 = state.tokens[i2];
|
|
9202
|
+
if (open2.type !== "blockquote_open") {
|
|
9170
9203
|
i2++;
|
|
9171
9204
|
continue;
|
|
9172
9205
|
}
|
|
@@ -9191,7 +9224,7 @@ Details: ${JSON.stringify(output)}` : "";
|
|
|
9191
9224
|
continue;
|
|
9192
9225
|
}
|
|
9193
9226
|
const type = match2[1].toLowerCase();
|
|
9194
|
-
|
|
9227
|
+
open2.attrSet("class", `markdown-alert markdown-alert-${type}`);
|
|
9195
9228
|
const rest = first.content.slice(match2[0].length);
|
|
9196
9229
|
if (rest) {
|
|
9197
9230
|
first.content = rest;
|
|
@@ -9729,8 +9762,8 @@ ${frontmatter.yaml}
|
|
|
9729
9762
|
|
|
9730
9763
|
// web-src/views/diff-line-select.ts
|
|
9731
9764
|
var SELECTED_CLASS = "gdp-diff-line-selected";
|
|
9732
|
-
function cardPath(
|
|
9733
|
-
return
|
|
9765
|
+
function cardPath(el2) {
|
|
9766
|
+
return el2.closest(".gdp-file-shell[data-path]")?.dataset.path || "";
|
|
9734
9767
|
}
|
|
9735
9768
|
function afterLineFromCell(cell) {
|
|
9736
9769
|
const sideCell = cell.closest("td.d2h-code-side-linenumber");
|
|
@@ -10076,6 +10109,7 @@ ${frontmatter.yaml}
|
|
|
10076
10109
|
const submit = document.createElement("button");
|
|
10077
10110
|
submit.type = "button";
|
|
10078
10111
|
submit.className = "gdp-btn gdp-btn-sm";
|
|
10112
|
+
if (opts.danger) submit.classList.add("gdp-dialog-danger");
|
|
10079
10113
|
submit.textContent = opts.submitLabel ?? "Save";
|
|
10080
10114
|
const error2 = document.createElement("div");
|
|
10081
10115
|
error2.className = "gdp-dialog-error";
|
|
@@ -10218,10 +10252,10 @@ ${frontmatter.yaml}
|
|
|
10218
10252
|
function updateDatabaseCaptureButton() {
|
|
10219
10253
|
annotationCaptureDb.hidden = deps.getRoute().screen !== "database";
|
|
10220
10254
|
}
|
|
10221
|
-
function setAnnotationPanelOpen(
|
|
10222
|
-
annotationPanel.hidden = !
|
|
10223
|
-
document.body.classList.toggle("annotation-panel-open",
|
|
10224
|
-
if (
|
|
10255
|
+
function setAnnotationPanelOpen(open2) {
|
|
10256
|
+
annotationPanel.hidden = !open2;
|
|
10257
|
+
document.body.classList.toggle("annotation-panel-open", open2);
|
|
10258
|
+
if (open2) {
|
|
10225
10259
|
annotationPanelDismissed = false;
|
|
10226
10260
|
const qhPanel = document.getElementById("query-history-panel");
|
|
10227
10261
|
if (qhPanel) qhPanel.hidden = true;
|
|
@@ -10232,7 +10266,7 @@ ${frontmatter.yaml}
|
|
|
10232
10266
|
updateActiveHighlights();
|
|
10233
10267
|
syncInlineAnnotationActive();
|
|
10234
10268
|
}
|
|
10235
|
-
deps.setAnnotationPanelOpenState(
|
|
10269
|
+
deps.setAnnotationPanelOpenState(open2);
|
|
10236
10270
|
syncSessionUrl();
|
|
10237
10271
|
applyInlineAnnotations();
|
|
10238
10272
|
}
|
|
@@ -10364,20 +10398,20 @@ ${frontmatter.yaml}
|
|
|
10364
10398
|
}
|
|
10365
10399
|
function applyDatabaseAnnotations(session) {
|
|
10366
10400
|
if (databaseAnnotationsMounted) {
|
|
10367
|
-
document.querySelectorAll(".gdp-db-annotation-strip").forEach((
|
|
10368
|
-
|
|
10401
|
+
document.querySelectorAll(".gdp-db-annotation-strip").forEach((el2) => {
|
|
10402
|
+
el2.remove();
|
|
10369
10403
|
});
|
|
10370
10404
|
databaseAnnotationsMounted = false;
|
|
10371
10405
|
}
|
|
10372
10406
|
if (!session || deps.getRoute().screen !== "database") return;
|
|
10373
|
-
const
|
|
10374
|
-
if (!
|
|
10407
|
+
const matches2 = session.entries.filter(databaseAnnotationMatchesRoute);
|
|
10408
|
+
if (!matches2.length) return;
|
|
10375
10409
|
const root = document.querySelector(".db-root");
|
|
10376
10410
|
if (!root) return;
|
|
10377
10411
|
const strip = document.createElement("section");
|
|
10378
10412
|
strip.className = "gdp-db-annotation-strip";
|
|
10379
10413
|
strip.setAttribute("aria-label", "Datastore annotations");
|
|
10380
|
-
for (const entry of
|
|
10414
|
+
for (const entry of matches2) {
|
|
10381
10415
|
strip.appendChild(
|
|
10382
10416
|
buildDatabaseAnnotationBlock(entry, {
|
|
10383
10417
|
index: session.entries.indexOf(entry),
|
|
@@ -10493,10 +10527,10 @@ ${frontmatter.yaml}
|
|
|
10493
10527
|
function syncInlineAnnotationWidths() {
|
|
10494
10528
|
document.querySelectorAll(".gdp-annotation-inline").forEach((box) => {
|
|
10495
10529
|
let scroller = null;
|
|
10496
|
-
for (let
|
|
10497
|
-
const overflowX = getComputedStyle(
|
|
10530
|
+
for (let el2 = box.parentElement; el2 && el2 !== document.body; el2 = el2.parentElement) {
|
|
10531
|
+
const overflowX = getComputedStyle(el2).overflowX;
|
|
10498
10532
|
if (overflowX === "auto" || overflowX === "scroll") {
|
|
10499
|
-
scroller =
|
|
10533
|
+
scroller = el2;
|
|
10500
10534
|
break;
|
|
10501
10535
|
}
|
|
10502
10536
|
}
|
|
@@ -10695,8 +10729,8 @@ ${frontmatter.yaml}
|
|
|
10695
10729
|
const head = annotationDetail.querySelector(
|
|
10696
10730
|
".annotation-detail-head"
|
|
10697
10731
|
);
|
|
10698
|
-
head?.querySelectorAll(".annotation-detail-head-action").forEach((
|
|
10699
|
-
|
|
10732
|
+
head?.querySelectorAll(".annotation-detail-head-action").forEach((el2) => {
|
|
10733
|
+
el2.remove();
|
|
10700
10734
|
});
|
|
10701
10735
|
const body = $("#annotation-detail-body");
|
|
10702
10736
|
body.replaceChildren();
|
|
@@ -10850,25 +10884,25 @@ ${frontmatter.yaml}
|
|
|
10850
10884
|
const item = document.createElement("li");
|
|
10851
10885
|
item.dataset.entryId = entry.id;
|
|
10852
10886
|
item.classList.toggle("active", entry.id === activeAnnotationId);
|
|
10853
|
-
const
|
|
10854
|
-
|
|
10855
|
-
|
|
10887
|
+
const open2 = document.createElement("button");
|
|
10888
|
+
open2.type = "button";
|
|
10889
|
+
open2.className = "annotation-entry-open";
|
|
10856
10890
|
const location2 = document.createElement("span");
|
|
10857
10891
|
location2.className = "annotation-entry-location";
|
|
10858
10892
|
location2.textContent = annotationLocationLabel(entry);
|
|
10859
10893
|
const summary = document.createElement("span");
|
|
10860
10894
|
summary.className = "annotation-entry-summary";
|
|
10861
10895
|
summary.textContent = annotationEntrySummary(entry);
|
|
10862
|
-
|
|
10896
|
+
open2.append(location2, summary);
|
|
10863
10897
|
const entryTimeLabel = annotationTimeLabel(entry.created_at);
|
|
10864
10898
|
if (entryTimeLabel) {
|
|
10865
10899
|
const time2 = document.createElement("span");
|
|
10866
10900
|
time2.className = "annotation-entry-time";
|
|
10867
10901
|
time2.textContent = entryTimeLabel;
|
|
10868
10902
|
time2.title = entry.created_at;
|
|
10869
|
-
|
|
10903
|
+
open2.appendChild(time2);
|
|
10870
10904
|
}
|
|
10871
|
-
|
|
10905
|
+
open2.addEventListener("click", () => {
|
|
10872
10906
|
void openAnnotationEntry(entry.id);
|
|
10873
10907
|
});
|
|
10874
10908
|
const remove = annotationIconButton(
|
|
@@ -10886,7 +10920,7 @@ ${frontmatter.yaml}
|
|
|
10886
10920
|
if (!ok) return;
|
|
10887
10921
|
void postAnnotationAction({ action: "delete", id: entry.id });
|
|
10888
10922
|
});
|
|
10889
|
-
item.append(
|
|
10923
|
+
item.append(open2, remove);
|
|
10890
10924
|
list2.appendChild(item);
|
|
10891
10925
|
});
|
|
10892
10926
|
sessionEl.appendChild(list2);
|
|
@@ -10894,13 +10928,13 @@ ${frontmatter.yaml}
|
|
|
10894
10928
|
}
|
|
10895
10929
|
}
|
|
10896
10930
|
function updateActiveHighlights() {
|
|
10897
|
-
annotationSessionsEl.querySelectorAll(".annotation-session").forEach((
|
|
10898
|
-
|
|
10931
|
+
annotationSessionsEl.querySelectorAll(".annotation-session").forEach((el2) => {
|
|
10932
|
+
el2.classList.toggle("active", el2.dataset.sessionId === activeSessionId);
|
|
10899
10933
|
});
|
|
10900
|
-
annotationSessionsEl.querySelectorAll(".annotation-entries li").forEach((
|
|
10901
|
-
|
|
10934
|
+
annotationSessionsEl.querySelectorAll(".annotation-entries li").forEach((el2) => {
|
|
10935
|
+
el2.classList.toggle(
|
|
10902
10936
|
"active",
|
|
10903
|
-
|
|
10937
|
+
el2.dataset.entryId === activeAnnotationId
|
|
10904
10938
|
);
|
|
10905
10939
|
});
|
|
10906
10940
|
}
|
|
@@ -10939,8 +10973,8 @@ ${frontmatter.yaml}
|
|
|
10939
10973
|
const head = annotationDetail.querySelector(
|
|
10940
10974
|
".annotation-detail-head"
|
|
10941
10975
|
);
|
|
10942
|
-
head?.querySelectorAll(".annotation-detail-head-action").forEach((
|
|
10943
|
-
|
|
10976
|
+
head?.querySelectorAll(".annotation-detail-head-action").forEach((el2) => {
|
|
10977
|
+
el2.remove();
|
|
10944
10978
|
});
|
|
10945
10979
|
const copyRef = createCopyRefButton(entry, "annotation-detail-head-action");
|
|
10946
10980
|
const edit = annotationIconButton(
|
|
@@ -11532,8 +11566,8 @@ ${frontmatter.yaml}
|
|
|
11532
11566
|
function createBlameView(deps) {
|
|
11533
11567
|
let activeGeneration = 0;
|
|
11534
11568
|
function cleanup() {
|
|
11535
|
-
document.querySelectorAll(".gdp-standalone-blame").forEach((
|
|
11536
|
-
|
|
11569
|
+
document.querySelectorAll(".gdp-standalone-blame").forEach((el2) => {
|
|
11570
|
+
el2.remove();
|
|
11537
11571
|
});
|
|
11538
11572
|
}
|
|
11539
11573
|
function colourBarFor(commit, bin, binCount) {
|
|
@@ -13102,16 +13136,16 @@ ${frontmatter.yaml}
|
|
|
13102
13136
|
}
|
|
13103
13137
|
|
|
13104
13138
|
// web-src/views/database/pane-status.ts
|
|
13105
|
-
function setPaneStatus(
|
|
13106
|
-
|
|
13139
|
+
function setPaneStatus(el2, message, options = {}) {
|
|
13140
|
+
el2.innerHTML = "";
|
|
13107
13141
|
options.afterClear?.();
|
|
13108
13142
|
const note = document.createElement("div");
|
|
13109
13143
|
note.className = options.error ? "db-pane-error" : "db-pane-note";
|
|
13110
13144
|
note.textContent = message;
|
|
13111
|
-
|
|
13145
|
+
el2.appendChild(note);
|
|
13112
13146
|
}
|
|
13113
|
-
function setPaneEmpty(
|
|
13114
|
-
|
|
13147
|
+
function setPaneEmpty(el2, message, options = {}) {
|
|
13148
|
+
el2.innerHTML = "";
|
|
13115
13149
|
const empty = document.createElement("div");
|
|
13116
13150
|
empty.className = "db-pane-empty";
|
|
13117
13151
|
const icon = document.createElement("div");
|
|
@@ -13127,7 +13161,7 @@ ${frontmatter.yaml}
|
|
|
13127
13161
|
hint.textContent = options.hint;
|
|
13128
13162
|
empty.appendChild(hint);
|
|
13129
13163
|
}
|
|
13130
|
-
|
|
13164
|
+
el2.appendChild(empty);
|
|
13131
13165
|
}
|
|
13132
13166
|
|
|
13133
13167
|
// web-src/views/database/dynamodb-explorer.ts
|
|
@@ -14821,9 +14855,9 @@ ${frontmatter.yaml}
|
|
|
14821
14855
|
}
|
|
14822
14856
|
function createErDiagram(deps = {}) {
|
|
14823
14857
|
const text3 = () => deps.getText?.() ?? dbText("en");
|
|
14824
|
-
const
|
|
14825
|
-
|
|
14826
|
-
|
|
14858
|
+
const el2 = document.createElement("div");
|
|
14859
|
+
el2.className = "db-er-diagram";
|
|
14860
|
+
el2.hidden = true;
|
|
14827
14861
|
const toolbar = document.createElement("div");
|
|
14828
14862
|
toolbar.className = "db-er-toolbar";
|
|
14829
14863
|
const zoomIn = document.createElement("button");
|
|
@@ -14853,7 +14887,7 @@ ${frontmatter.yaml}
|
|
|
14853
14887
|
});
|
|
14854
14888
|
const container = viewport.container;
|
|
14855
14889
|
const svgWrap = viewport.content;
|
|
14856
|
-
|
|
14890
|
+
el2.append(toolbar, container);
|
|
14857
14891
|
let lastMarkup = "";
|
|
14858
14892
|
zoomIn.addEventListener("click", () => viewport.zoomIn());
|
|
14859
14893
|
zoomOut.addEventListener("click", () => viewport.zoomOut());
|
|
@@ -14872,7 +14906,7 @@ ${frontmatter.yaml}
|
|
|
14872
14906
|
}
|
|
14873
14907
|
});
|
|
14874
14908
|
async function render(schema, columnsMap) {
|
|
14875
|
-
|
|
14909
|
+
el2.hidden = false;
|
|
14876
14910
|
svgWrap.innerHTML = "";
|
|
14877
14911
|
viewport.reset();
|
|
14878
14912
|
const tables = schema.tables.filter((t2) => t2.type === "table");
|
|
@@ -14898,7 +14932,7 @@ ${frontmatter.yaml}
|
|
|
14898
14932
|
}
|
|
14899
14933
|
}
|
|
14900
14934
|
function clear() {
|
|
14901
|
-
|
|
14935
|
+
el2.hidden = true;
|
|
14902
14936
|
svgWrap.innerHTML = "";
|
|
14903
14937
|
lastMarkup = "";
|
|
14904
14938
|
}
|
|
@@ -14914,14 +14948,14 @@ ${frontmatter.yaml}
|
|
|
14914
14948
|
copyBtn.title = t2.copyMermaidTitle;
|
|
14915
14949
|
if (copyBtn.textContent !== t2.copied) copyBtn.textContent = t2.copyMermaid;
|
|
14916
14950
|
}
|
|
14917
|
-
return { el, render, clear, dispose, localize };
|
|
14951
|
+
return { el: el2, render, clear, dispose, localize };
|
|
14918
14952
|
}
|
|
14919
14953
|
|
|
14920
14954
|
// web-src/views/database/global-search-view.ts
|
|
14921
14955
|
function createGlobalSearchView(deps) {
|
|
14922
14956
|
const text3 = () => deps.getText?.() ?? dbText("en");
|
|
14923
|
-
const
|
|
14924
|
-
|
|
14957
|
+
const el2 = document.createElement("div");
|
|
14958
|
+
el2.className = "db-global-search";
|
|
14925
14959
|
const header = document.createElement("div");
|
|
14926
14960
|
header.className = "db-global-search-header";
|
|
14927
14961
|
const input2 = document.createElement("input");
|
|
@@ -14951,7 +14985,7 @@ ${frontmatter.yaml}
|
|
|
14951
14985
|
progress.hidden = true;
|
|
14952
14986
|
const results = document.createElement("div");
|
|
14953
14987
|
results.className = "db-global-search-results";
|
|
14954
|
-
|
|
14988
|
+
el2.append(header, optionsRow, progress, results);
|
|
14955
14989
|
let currentJobId = null;
|
|
14956
14990
|
let pollTimer = null;
|
|
14957
14991
|
let disposed = false;
|
|
@@ -15147,7 +15181,7 @@ ${frontmatter.yaml}
|
|
|
15147
15181
|
cancelBtn.textContent = t2.cancelButton;
|
|
15148
15182
|
nonTextText.textContent = t2.includeNonText;
|
|
15149
15183
|
}
|
|
15150
|
-
return { el, setSearch, getSearch, dispose, localize };
|
|
15184
|
+
return { el: el2, setSearch, getSearch, dispose, localize };
|
|
15151
15185
|
}
|
|
15152
15186
|
|
|
15153
15187
|
// web-src/views/database/pref-toggle.ts
|
|
@@ -15196,8 +15230,8 @@ ${frontmatter.yaml}
|
|
|
15196
15230
|
var MAX_HISTORY = 50;
|
|
15197
15231
|
function createQueryEditor(callbacks) {
|
|
15198
15232
|
const text3 = () => callbacks.getText?.() ?? dbText("en");
|
|
15199
|
-
const
|
|
15200
|
-
|
|
15233
|
+
const el2 = document.createElement("div");
|
|
15234
|
+
el2.className = "db-query-editor";
|
|
15201
15235
|
const inputArea = document.createElement("div");
|
|
15202
15236
|
inputArea.className = "db-query-input";
|
|
15203
15237
|
const editorWrap = document.createElement("div");
|
|
@@ -15275,7 +15309,7 @@ ${frontmatter.yaml}
|
|
|
15275
15309
|
const resultArea = document.createElement("div");
|
|
15276
15310
|
resultArea.className = "db-query-result";
|
|
15277
15311
|
resultArea.hidden = true;
|
|
15278
|
-
|
|
15312
|
+
el2.append(inputArea, resultArea);
|
|
15279
15313
|
async function run() {
|
|
15280
15314
|
const sql = textarea.value.trim();
|
|
15281
15315
|
if (!sql) return;
|
|
@@ -15510,7 +15544,7 @@ ${frontmatter.yaml}
|
|
|
15510
15544
|
historyBtn.title = t2.localHistoryTitle;
|
|
15511
15545
|
}
|
|
15512
15546
|
return {
|
|
15513
|
-
el,
|
|
15547
|
+
el: el2,
|
|
15514
15548
|
focus,
|
|
15515
15549
|
setSql,
|
|
15516
15550
|
getSql,
|
|
@@ -15524,8 +15558,8 @@ ${frontmatter.yaml}
|
|
|
15524
15558
|
// web-src/views/database/query-history-view.ts
|
|
15525
15559
|
function createQueryHistoryView(callbacks) {
|
|
15526
15560
|
const text3 = () => callbacks.getText?.() ?? dbText("en");
|
|
15527
|
-
const
|
|
15528
|
-
|
|
15561
|
+
const el2 = document.createElement("div");
|
|
15562
|
+
el2.className = "db-query-history";
|
|
15529
15563
|
const toolbar = document.createElement("div");
|
|
15530
15564
|
toolbar.className = "db-query-history-toolbar";
|
|
15531
15565
|
const refreshBtn = document.createElement("button");
|
|
@@ -15559,7 +15593,7 @@ ${frontmatter.yaml}
|
|
|
15559
15593
|
detailPlaceholder.textContent = text3().history.selectPlaceholder;
|
|
15560
15594
|
detailCol.appendChild(detailPlaceholder);
|
|
15561
15595
|
body.append(listCol, detailCol);
|
|
15562
|
-
|
|
15596
|
+
el2.append(toolbar, body);
|
|
15563
15597
|
let entries = [];
|
|
15564
15598
|
const expandedIds = /* @__PURE__ */ new Set();
|
|
15565
15599
|
let clearConfirmTimer = null;
|
|
@@ -15967,7 +16001,7 @@ ${frontmatter.yaml}
|
|
|
15967
16001
|
}
|
|
15968
16002
|
}
|
|
15969
16003
|
}
|
|
15970
|
-
return { el, refresh, clear, localize };
|
|
16004
|
+
return { el: el2, refresh, clear, localize };
|
|
15971
16005
|
}
|
|
15972
16006
|
function formatTime(iso) {
|
|
15973
16007
|
try {
|
|
@@ -15983,17 +16017,17 @@ ${frontmatter.yaml}
|
|
|
15983
16017
|
function isBinaryItem(item) {
|
|
15984
16018
|
return typeof item === "object" && item !== null && "binaryBase64" in item;
|
|
15985
16019
|
}
|
|
15986
|
-
function renderItemInto(
|
|
15987
|
-
|
|
16020
|
+
function renderItemInto(el2, item, binaryBadge) {
|
|
16021
|
+
el2.textContent = "";
|
|
15988
16022
|
if (isBinaryItem(item)) {
|
|
15989
16023
|
const badge = document.createElement("span");
|
|
15990
16024
|
badge.className = "redis-binary-badge";
|
|
15991
16025
|
badge.textContent = binaryBadge;
|
|
15992
|
-
|
|
15993
|
-
|
|
16026
|
+
el2.appendChild(badge);
|
|
16027
|
+
el2.appendChild(document.createTextNode(item.binaryBase64));
|
|
15994
16028
|
return;
|
|
15995
16029
|
}
|
|
15996
|
-
|
|
16030
|
+
el2.textContent = item;
|
|
15997
16031
|
}
|
|
15998
16032
|
function createRedisExplorer(callbacks = {}) {
|
|
15999
16033
|
const text3 = () => (callbacks.getText?.() ?? dbText("en")).explorer;
|
|
@@ -17207,8 +17241,8 @@ ${frontmatter.yaml}
|
|
|
17207
17241
|
function isAbortError(err) {
|
|
17208
17242
|
return err instanceof DOMException && err.name === "AbortError";
|
|
17209
17243
|
}
|
|
17210
|
-
function setExplorerFolderIcon(
|
|
17211
|
-
|
|
17244
|
+
function setExplorerFolderIcon(el2, collapsed) {
|
|
17245
|
+
el2.innerHTML = iconSvg(
|
|
17212
17246
|
collapsed ? "octicon-file-directory-fill" : "octicon-file-directory-open-fill",
|
|
17213
17247
|
collapsed ? FOLDER_ICON_PATHS.closed : FOLDER_ICON_PATHS.open
|
|
17214
17248
|
);
|
|
@@ -17767,12 +17801,12 @@ ${frontmatter.yaml}
|
|
|
17767
17801
|
actions.className = "s3-preview-actions";
|
|
17768
17802
|
if (currentDbId && currentBucket) {
|
|
17769
17803
|
const rawUrl = buildS3RawUrl(currentDbId, currentBucket, object.key);
|
|
17770
|
-
const
|
|
17771
|
-
|
|
17772
|
-
|
|
17773
|
-
|
|
17774
|
-
|
|
17775
|
-
|
|
17804
|
+
const open2 = document.createElement("a");
|
|
17805
|
+
open2.className = "db-btn db-btn-sm";
|
|
17806
|
+
open2.href = rawUrl;
|
|
17807
|
+
open2.target = "_blank";
|
|
17808
|
+
open2.rel = "noreferrer";
|
|
17809
|
+
open2.textContent = text3().openRaw;
|
|
17776
17810
|
const download = document.createElement("a");
|
|
17777
17811
|
download.className = "db-btn db-btn-sm";
|
|
17778
17812
|
download.href = rawUrl;
|
|
@@ -17795,7 +17829,7 @@ ${frontmatter.yaml}
|
|
|
17795
17829
|
copy.textContent = text3().copyFailed;
|
|
17796
17830
|
}
|
|
17797
17831
|
});
|
|
17798
|
-
actions.append(
|
|
17832
|
+
actions.append(open2, download, copy);
|
|
17799
17833
|
if (sourceDisplayKind(object.key) === "text") {
|
|
17800
17834
|
const editBtn = mkBtn(tCommon().edit, "db-btn db-btn-sm");
|
|
17801
17835
|
editBtn.addEventListener("click", () => void startObjectEdit(object));
|
|
@@ -17922,8 +17956,8 @@ ${frontmatter.yaml}
|
|
|
17922
17956
|
function indentPad(depth) {
|
|
17923
17957
|
return `${12 + depth * 14}px`;
|
|
17924
17958
|
}
|
|
17925
|
-
function setExplorerChevron(
|
|
17926
|
-
|
|
17959
|
+
function setExplorerChevron(el2) {
|
|
17960
|
+
el2.innerHTML = `<svg class="octicon octicon-chevron-down" viewBox="0 0 12 12" width="12" height="12" fill="currentColor" aria-hidden="true"><path fill="currentColor" d="${CHEVRON_DOWN_12_PATH}"></path></svg>`;
|
|
17927
17961
|
}
|
|
17928
17962
|
function resetExplorer() {
|
|
17929
17963
|
explorerAbort?.abort();
|
|
@@ -17951,11 +17985,11 @@ ${frontmatter.yaml}
|
|
|
17951
17985
|
return await res.json();
|
|
17952
17986
|
}
|
|
17953
17987
|
function makeTreeMessageRow(cls, depth, text4) {
|
|
17954
|
-
const
|
|
17955
|
-
|
|
17956
|
-
|
|
17957
|
-
|
|
17958
|
-
return
|
|
17988
|
+
const el2 = document.createElement("div");
|
|
17989
|
+
el2.className = cls;
|
|
17990
|
+
el2.style.setProperty("--lvl-pad", indentPad(depth));
|
|
17991
|
+
el2.textContent = text4;
|
|
17992
|
+
return el2;
|
|
17959
17993
|
}
|
|
17960
17994
|
function createExplorerFileRow(object, depth) {
|
|
17961
17995
|
objectsByKey.set(object.key, object);
|
|
@@ -18422,9 +18456,9 @@ ${frontmatter.yaml}
|
|
|
18422
18456
|
// web-src/views/database/schema-view.ts
|
|
18423
18457
|
function createSchemaView(deps = {}) {
|
|
18424
18458
|
const text3 = () => deps.getText?.() ?? dbText("en");
|
|
18425
|
-
const
|
|
18426
|
-
|
|
18427
|
-
|
|
18459
|
+
const el2 = document.createElement("div");
|
|
18460
|
+
el2.className = "db-schema-view";
|
|
18461
|
+
el2.hidden = true;
|
|
18428
18462
|
let refreshBusy = false;
|
|
18429
18463
|
let refreshBtn = null;
|
|
18430
18464
|
let refreshLabel = null;
|
|
@@ -18446,8 +18480,8 @@ ${frontmatter.yaml}
|
|
|
18446
18480
|
function render(table2, columns, indexes, extra) {
|
|
18447
18481
|
lastArgs = { table: table2, columns, indexes, extra };
|
|
18448
18482
|
const t2 = text3().schema;
|
|
18449
|
-
|
|
18450
|
-
|
|
18483
|
+
el2.hidden = false;
|
|
18484
|
+
el2.innerHTML = "";
|
|
18451
18485
|
const header = document.createElement("div");
|
|
18452
18486
|
header.className = "db-schema-header";
|
|
18453
18487
|
const headerTitle = document.createElement("span");
|
|
@@ -18473,11 +18507,11 @@ ${frontmatter.yaml}
|
|
|
18473
18507
|
refreshBtn = null;
|
|
18474
18508
|
refreshLabel = null;
|
|
18475
18509
|
}
|
|
18476
|
-
|
|
18510
|
+
el2.appendChild(header);
|
|
18477
18511
|
const colSectionHeader = document.createElement("div");
|
|
18478
18512
|
colSectionHeader.className = "db-schema-section-header";
|
|
18479
18513
|
colSectionHeader.textContent = t2.columns;
|
|
18480
|
-
|
|
18514
|
+
el2.appendChild(colSectionHeader);
|
|
18481
18515
|
const colTable = document.createElement("table");
|
|
18482
18516
|
colTable.className = "db-schema-table";
|
|
18483
18517
|
const thead = document.createElement("thead");
|
|
@@ -18520,13 +18554,13 @@ ${frontmatter.yaml}
|
|
|
18520
18554
|
tbody.appendChild(tr);
|
|
18521
18555
|
}
|
|
18522
18556
|
colTable.append(thead, tbody);
|
|
18523
|
-
|
|
18557
|
+
el2.appendChild(colTable);
|
|
18524
18558
|
const fks = extra?.foreignKeys?.filter((fk) => fk.fromTable === table2);
|
|
18525
18559
|
if (fks && fks.length > 0) {
|
|
18526
18560
|
const fkHeader = document.createElement("div");
|
|
18527
18561
|
fkHeader.className = "db-schema-section-header";
|
|
18528
18562
|
fkHeader.textContent = t2.foreignKeys;
|
|
18529
|
-
|
|
18563
|
+
el2.appendChild(fkHeader);
|
|
18530
18564
|
const fkTable = document.createElement("table");
|
|
18531
18565
|
fkTable.className = "db-schema-table";
|
|
18532
18566
|
const fkThead = document.createElement("thead");
|
|
@@ -18550,14 +18584,14 @@ ${frontmatter.yaml}
|
|
|
18550
18584
|
fkTbody.appendChild(tr);
|
|
18551
18585
|
}
|
|
18552
18586
|
fkTable.append(fkThead, fkTbody);
|
|
18553
|
-
|
|
18587
|
+
el2.appendChild(fkTable);
|
|
18554
18588
|
}
|
|
18555
18589
|
const tableIndexes = indexes.filter((idx) => idx.table === table2);
|
|
18556
18590
|
if (tableIndexes.length > 0) {
|
|
18557
18591
|
const idxHeader = document.createElement("div");
|
|
18558
18592
|
idxHeader.className = "db-schema-section-header";
|
|
18559
18593
|
idxHeader.textContent = t2.indexes;
|
|
18560
|
-
|
|
18594
|
+
el2.appendChild(idxHeader);
|
|
18561
18595
|
const idxTable = document.createElement("table");
|
|
18562
18596
|
idxTable.className = "db-schema-table";
|
|
18563
18597
|
const idxThead = document.createElement("thead");
|
|
@@ -18581,14 +18615,14 @@ ${frontmatter.yaml}
|
|
|
18581
18615
|
idxTbody.appendChild(tr);
|
|
18582
18616
|
}
|
|
18583
18617
|
idxTable.append(idxThead, idxTbody);
|
|
18584
|
-
|
|
18618
|
+
el2.appendChild(idxTable);
|
|
18585
18619
|
}
|
|
18586
18620
|
const triggers = extra?.triggers;
|
|
18587
18621
|
if (triggers && triggers.length > 0) {
|
|
18588
18622
|
const trigHeader = document.createElement("div");
|
|
18589
18623
|
trigHeader.className = "db-schema-section-header";
|
|
18590
18624
|
trigHeader.textContent = t2.triggers;
|
|
18591
|
-
|
|
18625
|
+
el2.appendChild(trigHeader);
|
|
18592
18626
|
for (const trig of triggers) {
|
|
18593
18627
|
const trigBlock = document.createElement("div");
|
|
18594
18628
|
trigBlock.className = "db-schema-trigger-block";
|
|
@@ -18599,7 +18633,7 @@ ${frontmatter.yaml}
|
|
|
18599
18633
|
trigPre.className = "db-schema-ddl-pre";
|
|
18600
18634
|
trigPre.textContent = trig.sql;
|
|
18601
18635
|
trigBlock.append(trigName, trigPre);
|
|
18602
|
-
|
|
18636
|
+
el2.appendChild(trigBlock);
|
|
18603
18637
|
}
|
|
18604
18638
|
}
|
|
18605
18639
|
const ddl = extra?.ddl;
|
|
@@ -18607,7 +18641,7 @@ ${frontmatter.yaml}
|
|
|
18607
18641
|
const ddlHeader = document.createElement("div");
|
|
18608
18642
|
ddlHeader.className = "db-schema-section-header";
|
|
18609
18643
|
ddlHeader.textContent = t2.ddl;
|
|
18610
|
-
|
|
18644
|
+
el2.appendChild(ddlHeader);
|
|
18611
18645
|
const ddlWrap = document.createElement("div");
|
|
18612
18646
|
ddlWrap.className = "db-schema-ddl-wrap";
|
|
18613
18647
|
const copyBtn = document.createElement("button");
|
|
@@ -18630,22 +18664,22 @@ ${frontmatter.yaml}
|
|
|
18630
18664
|
ddlPre.className = "db-schema-ddl-pre";
|
|
18631
18665
|
ddlPre.textContent = ddl;
|
|
18632
18666
|
ddlWrap.append(copyBtn, ddlPre);
|
|
18633
|
-
|
|
18667
|
+
el2.appendChild(ddlWrap);
|
|
18634
18668
|
}
|
|
18635
18669
|
}
|
|
18636
18670
|
function clear() {
|
|
18637
|
-
|
|
18638
|
-
|
|
18671
|
+
el2.hidden = true;
|
|
18672
|
+
el2.innerHTML = "";
|
|
18639
18673
|
lastArgs = null;
|
|
18640
18674
|
refreshBtn = null;
|
|
18641
18675
|
refreshLabel = null;
|
|
18642
18676
|
refreshBusy = false;
|
|
18643
18677
|
}
|
|
18644
18678
|
function localize() {
|
|
18645
|
-
if (!lastArgs ||
|
|
18679
|
+
if (!lastArgs || el2.hidden) return;
|
|
18646
18680
|
render(lastArgs.table, lastArgs.columns, lastArgs.indexes, lastArgs.extra);
|
|
18647
18681
|
}
|
|
18648
|
-
return { el, render, clear, localize, setRefreshBusy };
|
|
18682
|
+
return { el: el2, render, clear, localize, setRefreshBusy };
|
|
18649
18683
|
}
|
|
18650
18684
|
|
|
18651
18685
|
// web-src/views/database/session-log.ts
|
|
@@ -18688,8 +18722,8 @@ ${frontmatter.yaml}
|
|
|
18688
18722
|
// web-src/views/database/session-log-view.ts
|
|
18689
18723
|
function createSessionLogView(callbacks) {
|
|
18690
18724
|
const text3 = () => callbacks.getText?.() ?? dbText("en");
|
|
18691
|
-
const
|
|
18692
|
-
|
|
18725
|
+
const el2 = document.createElement("div");
|
|
18726
|
+
el2.className = "db-session-log";
|
|
18693
18727
|
const toolbar = document.createElement("div");
|
|
18694
18728
|
toolbar.className = "db-session-log-toolbar";
|
|
18695
18729
|
const followBtn = document.createElement("button");
|
|
@@ -18718,7 +18752,7 @@ ${frontmatter.yaml}
|
|
|
18718
18752
|
placeholder.textContent = text3().sessionLog.selectPlaceholder;
|
|
18719
18753
|
detailCol.appendChild(placeholder);
|
|
18720
18754
|
body.append(listCol, detailCol);
|
|
18721
|
-
|
|
18755
|
+
el2.append(toolbar, body);
|
|
18722
18756
|
let selectedId = null;
|
|
18723
18757
|
const rowById = /* @__PURE__ */ new Map();
|
|
18724
18758
|
let autoFollow = true;
|
|
@@ -18906,7 +18940,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
18906
18940
|
placeholder.textContent = text3().sessionLog.selectPlaceholder;
|
|
18907
18941
|
render();
|
|
18908
18942
|
}
|
|
18909
|
-
return { el, clear, localize };
|
|
18943
|
+
return { el: el2, clear, localize };
|
|
18910
18944
|
}
|
|
18911
18945
|
function formatTime2(timestamp) {
|
|
18912
18946
|
const d2 = new Date(timestamp);
|
|
@@ -18944,8 +18978,8 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
18944
18978
|
const note = s2.note ? ` — ${s2.note}` : "";
|
|
18945
18979
|
return text3().snapshot.label(date, s2.tables.length, note);
|
|
18946
18980
|
};
|
|
18947
|
-
const
|
|
18948
|
-
|
|
18981
|
+
const el2 = document.createElement("div");
|
|
18982
|
+
el2.className = "db-snapshot-view";
|
|
18949
18983
|
const guide = document.createElement("div");
|
|
18950
18984
|
guide.className = "db-snapshot-guide";
|
|
18951
18985
|
const guideTitle = document.createElement("div");
|
|
@@ -19039,7 +19073,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
19039
19073
|
rightPane.className = "db-snapshot-right-pane";
|
|
19040
19074
|
splitContainer.append(leftPane, rightPane);
|
|
19041
19075
|
mainArea.appendChild(splitContainer);
|
|
19042
|
-
|
|
19076
|
+
el2.append(guide, toolbar, progressArea, tableSelector, mainArea);
|
|
19043
19077
|
let snapshots = [];
|
|
19044
19078
|
let currentDiff = null;
|
|
19045
19079
|
let disposed = false;
|
|
@@ -19717,8 +19751,8 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
19717
19751
|
threshold: 0
|
|
19718
19752
|
}
|
|
19719
19753
|
);
|
|
19720
|
-
for (const
|
|
19721
|
-
observer.observe(
|
|
19754
|
+
for (const el3 of section2.querySelectorAll(".db-snapshot-diff-table")) {
|
|
19755
|
+
observer.observe(el3);
|
|
19722
19756
|
}
|
|
19723
19757
|
section2.__tocObserver = observer;
|
|
19724
19758
|
rightPane.appendChild(section2);
|
|
@@ -19877,7 +19911,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
19877
19911
|
}
|
|
19878
19912
|
}
|
|
19879
19913
|
async function editNote(snapshotId, currentNote) {
|
|
19880
|
-
const existing =
|
|
19914
|
+
const existing = el2.querySelector(".db-snapshot-inline-dialog");
|
|
19881
19915
|
if (existing) existing.remove();
|
|
19882
19916
|
const dialog = document.createElement("div");
|
|
19883
19917
|
dialog.className = "db-snapshot-inline-dialog";
|
|
@@ -19911,7 +19945,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
19911
19945
|
});
|
|
19912
19946
|
dialog.append(input2, saveBtn, cancelDlgBtn);
|
|
19913
19947
|
const item = Array.from(
|
|
19914
|
-
|
|
19948
|
+
el2.querySelectorAll(".db-snapshot-item")
|
|
19915
19949
|
).find((node) => node.dataset.snapshotId === snapshotId);
|
|
19916
19950
|
if (item) {
|
|
19917
19951
|
item.after(dialog);
|
|
@@ -20040,7 +20074,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
20040
20074
|
await showDiffInline(target.before, target.after);
|
|
20041
20075
|
}
|
|
20042
20076
|
return {
|
|
20043
|
-
el,
|
|
20077
|
+
el: el2,
|
|
20044
20078
|
refresh,
|
|
20045
20079
|
handleSse,
|
|
20046
20080
|
dispose,
|
|
@@ -20067,8 +20101,8 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
20067
20101
|
function createTableGrid(callbacks, options = {}) {
|
|
20068
20102
|
const embedded = options.embedded === true;
|
|
20069
20103
|
const text3 = () => callbacks.getText?.() ?? dbText("en");
|
|
20070
|
-
const
|
|
20071
|
-
|
|
20104
|
+
const el2 = document.createElement("div");
|
|
20105
|
+
el2.className = "db-grid";
|
|
20072
20106
|
const filterBar = document.createElement("div");
|
|
20073
20107
|
filterBar.className = "db-grid-filter-bar";
|
|
20074
20108
|
const filterIcon = document.createElement("span");
|
|
@@ -20243,9 +20277,9 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
20243
20277
|
detailResize.addEventListener("mousedown", startDetailResize);
|
|
20244
20278
|
detailPanel.appendChild(detailResize);
|
|
20245
20279
|
viewport.append(spacer, body, filteredEmpty);
|
|
20246
|
-
|
|
20280
|
+
el2.append(filterBar, headerWrap, filterRowWrap, viewport, detailPanel);
|
|
20247
20281
|
function panelMaxHeight() {
|
|
20248
|
-
const containerH =
|
|
20282
|
+
const containerH = el2.clientHeight || window.innerHeight;
|
|
20249
20283
|
return Math.max(
|
|
20250
20284
|
DETAIL_PANEL_MIN_HEIGHT + 1,
|
|
20251
20285
|
containerH - PANEL_MAX_RESERVE
|
|
@@ -20383,7 +20417,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
20383
20417
|
relatedPanel.className = "db-related-panel";
|
|
20384
20418
|
relatedPanel.hidden = true;
|
|
20385
20419
|
relatedPanel.style.height = `${relatedHeight}px`;
|
|
20386
|
-
|
|
20420
|
+
el2.appendChild(relatedPanel);
|
|
20387
20421
|
}
|
|
20388
20422
|
const colWidths = /* @__PURE__ */ new Map();
|
|
20389
20423
|
let activeResize = null;
|
|
@@ -21611,7 +21645,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
21611
21645
|
if (!statusEl) {
|
|
21612
21646
|
statusEl = document.createElement("div");
|
|
21613
21647
|
statusEl.className = "db-grid-status";
|
|
21614
|
-
|
|
21648
|
+
el2.appendChild(statusEl);
|
|
21615
21649
|
}
|
|
21616
21650
|
const t2 = text3().grid;
|
|
21617
21651
|
const parts = [t2.statusRows(totalRows.toLocaleString())];
|
|
@@ -21636,7 +21670,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
21636
21670
|
statusEl = document.createElement("div");
|
|
21637
21671
|
statusEl.className = "db-grid-status db-pane-error";
|
|
21638
21672
|
statusEl.textContent = message;
|
|
21639
|
-
|
|
21673
|
+
el2.appendChild(statusEl);
|
|
21640
21674
|
}
|
|
21641
21675
|
function load(table2, initialData) {
|
|
21642
21676
|
clear();
|
|
@@ -21857,12 +21891,12 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
21857
21891
|
discardBtn.disabled = count === 0;
|
|
21858
21892
|
notifyEditableIfChanged();
|
|
21859
21893
|
}
|
|
21860
|
-
function setControlVisibility(
|
|
21861
|
-
|
|
21862
|
-
if ("tabIndex" in
|
|
21863
|
-
|
|
21894
|
+
function setControlVisibility(el3, visible) {
|
|
21895
|
+
el3.style.visibility = visible ? "" : "hidden";
|
|
21896
|
+
if ("tabIndex" in el3) {
|
|
21897
|
+
el3.tabIndex = visible ? 0 : -1;
|
|
21864
21898
|
}
|
|
21865
|
-
|
|
21899
|
+
el3.setAttribute("aria-hidden", visible ? "false" : "true");
|
|
21866
21900
|
}
|
|
21867
21901
|
const editableListeners = /* @__PURE__ */ new Set();
|
|
21868
21902
|
const editModeListeners = /* @__PURE__ */ new Set();
|
|
@@ -22018,7 +22052,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22018
22052
|
embeddedGrid?.refreshForeignKeys();
|
|
22019
22053
|
}
|
|
22020
22054
|
return {
|
|
22021
|
-
el,
|
|
22055
|
+
el: el2,
|
|
22022
22056
|
load,
|
|
22023
22057
|
refresh: refreshCurrentTable,
|
|
22024
22058
|
showError,
|
|
@@ -22078,9 +22112,9 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22078
22112
|
filterClear.innerHTML = iconSvg("octicon-x", X_16_PATH);
|
|
22079
22113
|
filterClear.hidden = true;
|
|
22080
22114
|
filterWrap.append(filterInput, filterClear);
|
|
22081
|
-
const
|
|
22082
|
-
|
|
22083
|
-
wrapper.append(filterWrap,
|
|
22115
|
+
const el2 = document.createElement("div");
|
|
22116
|
+
el2.className = "db-table-list";
|
|
22117
|
+
wrapper.append(filterWrap, el2);
|
|
22084
22118
|
let activeTable = null;
|
|
22085
22119
|
let allTables = [];
|
|
22086
22120
|
const expandedTables = /* @__PURE__ */ new Set();
|
|
@@ -22089,7 +22123,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22089
22123
|
let contextMenuClick = null;
|
|
22090
22124
|
let contextMenuKeyDown = null;
|
|
22091
22125
|
let contextMenuTimer = null;
|
|
22092
|
-
function
|
|
22126
|
+
function closeContextMenu2() {
|
|
22093
22127
|
if (contextMenuTimer) {
|
|
22094
22128
|
clearTimeout(contextMenuTimer);
|
|
22095
22129
|
contextMenuTimer = null;
|
|
@@ -22107,9 +22141,9 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22107
22141
|
contextMenu = null;
|
|
22108
22142
|
}
|
|
22109
22143
|
}
|
|
22110
|
-
function
|
|
22144
|
+
function showContextMenu2(e2, tableName) {
|
|
22111
22145
|
e2.preventDefault();
|
|
22112
|
-
|
|
22146
|
+
closeContextMenu2();
|
|
22113
22147
|
const menu = document.createElement("div");
|
|
22114
22148
|
menu.className = "db-context-menu";
|
|
22115
22149
|
menu.style.position = "absolute";
|
|
@@ -22150,7 +22184,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22150
22184
|
row.textContent = item.label;
|
|
22151
22185
|
row.addEventListener("click", () => {
|
|
22152
22186
|
item.action();
|
|
22153
|
-
|
|
22187
|
+
closeContextMenu2();
|
|
22154
22188
|
});
|
|
22155
22189
|
menu.appendChild(row);
|
|
22156
22190
|
}
|
|
@@ -22158,13 +22192,13 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22158
22192
|
contextMenu = menu;
|
|
22159
22193
|
const onDocClick = (ev) => {
|
|
22160
22194
|
if (!menu.contains(ev.target)) {
|
|
22161
|
-
|
|
22195
|
+
closeContextMenu2();
|
|
22162
22196
|
}
|
|
22163
22197
|
};
|
|
22164
22198
|
const onKeyDown = (ev) => {
|
|
22165
22199
|
if (isImeComposing(ev)) return;
|
|
22166
22200
|
if (ev.key === "Escape") {
|
|
22167
|
-
|
|
22201
|
+
closeContextMenu2();
|
|
22168
22202
|
}
|
|
22169
22203
|
};
|
|
22170
22204
|
contextMenuClick = onDocClick;
|
|
@@ -22246,7 +22280,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22246
22280
|
filterInput.focus();
|
|
22247
22281
|
}
|
|
22248
22282
|
function renderFiltered(tables, filter) {
|
|
22249
|
-
|
|
22283
|
+
el2.innerHTML = "";
|
|
22250
22284
|
syncFilterClearButton();
|
|
22251
22285
|
const filtered = filter ? tables.filter(
|
|
22252
22286
|
(t2) => t2.name.toLowerCase().includes(filter.toLowerCase())
|
|
@@ -22268,7 +22302,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22268
22302
|
actions.appendChild(clear);
|
|
22269
22303
|
empty.appendChild(actions);
|
|
22270
22304
|
}
|
|
22271
|
-
|
|
22305
|
+
el2.appendChild(empty);
|
|
22272
22306
|
return;
|
|
22273
22307
|
}
|
|
22274
22308
|
const groups = { table: [], view: [] };
|
|
@@ -22280,7 +22314,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22280
22314
|
const header = document.createElement("div");
|
|
22281
22315
|
header.className = "db-table-group-header";
|
|
22282
22316
|
header.textContent = type === "view" ? "Views" : "Tables";
|
|
22283
|
-
|
|
22317
|
+
el2.appendChild(header);
|
|
22284
22318
|
for (const table2 of items) {
|
|
22285
22319
|
const node = document.createElement("div");
|
|
22286
22320
|
node.className = "db-table-node";
|
|
@@ -22329,10 +22363,10 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22329
22363
|
);
|
|
22330
22364
|
row.addEventListener(
|
|
22331
22365
|
"contextmenu",
|
|
22332
|
-
(e2) =>
|
|
22366
|
+
(e2) => showContextMenu2(e2, table2.name)
|
|
22333
22367
|
);
|
|
22334
22368
|
node.append(row, children);
|
|
22335
|
-
|
|
22369
|
+
el2.appendChild(node);
|
|
22336
22370
|
}
|
|
22337
22371
|
}
|
|
22338
22372
|
}
|
|
@@ -22345,7 +22379,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22345
22379
|
}
|
|
22346
22380
|
columnCache.clear();
|
|
22347
22381
|
activeTable = null;
|
|
22348
|
-
|
|
22382
|
+
closeContextMenu2();
|
|
22349
22383
|
filterInput.value = "";
|
|
22350
22384
|
renderFiltered(tables, "");
|
|
22351
22385
|
}
|
|
@@ -22356,7 +22390,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22356
22390
|
filterClear.addEventListener("click", clearFilter);
|
|
22357
22391
|
function setActive(table2) {
|
|
22358
22392
|
activeTable = table2;
|
|
22359
|
-
|
|
22393
|
+
el2.querySelectorAll(".db-table-item").forEach((item) => {
|
|
22360
22394
|
item.classList.toggle("active", item.dataset.table === table2);
|
|
22361
22395
|
});
|
|
22362
22396
|
}
|
|
@@ -22364,7 +22398,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22364
22398
|
allTables = allTables.map(
|
|
22365
22399
|
(entry) => entry.name === table2 ? { ...entry, rowCount } : entry
|
|
22366
22400
|
);
|
|
22367
|
-
for (const node of
|
|
22401
|
+
for (const node of el2.querySelectorAll(".db-table-node")) {
|
|
22368
22402
|
if (node.dataset.table !== table2) continue;
|
|
22369
22403
|
const count = node.querySelector(".db-table-count");
|
|
22370
22404
|
if (count)
|
|
@@ -22372,7 +22406,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22372
22406
|
}
|
|
22373
22407
|
}
|
|
22374
22408
|
function dispose() {
|
|
22375
|
-
|
|
22409
|
+
closeContextMenu2();
|
|
22376
22410
|
allTables = [];
|
|
22377
22411
|
expandedTables.clear();
|
|
22378
22412
|
columnCache.clear();
|
|
@@ -25234,11 +25268,11 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
25234
25268
|
return !!text3 && !/\S/.test(text3);
|
|
25235
25269
|
}
|
|
25236
25270
|
function suppressWhitespaceOnlyInlineHighlights(root) {
|
|
25237
|
-
root.querySelectorAll("ins, del").forEach((
|
|
25238
|
-
if (!isWhitespaceOnlyInlineHighlight(
|
|
25239
|
-
const parent =
|
|
25271
|
+
root.querySelectorAll("ins, del").forEach((el2) => {
|
|
25272
|
+
if (!isWhitespaceOnlyInlineHighlight(el2.textContent)) return;
|
|
25273
|
+
const parent = el2.parentNode;
|
|
25240
25274
|
if (!parent) return;
|
|
25241
|
-
parent.replaceChild(document.createTextNode(
|
|
25275
|
+
parent.replaceChild(document.createTextNode(el2.textContent || ""), el2);
|
|
25242
25276
|
});
|
|
25243
25277
|
}
|
|
25244
25278
|
|
|
@@ -25365,12 +25399,12 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
25365
25399
|
button.innerHTML = expanded ? iconSvg("octicon-fold", COLLAPSE_ALL_16_PATHS) : iconSvg("octicon-unfold", EXPAND_ALL_16_PATHS);
|
|
25366
25400
|
}
|
|
25367
25401
|
function setProjectBranch(branch) {
|
|
25368
|
-
const
|
|
25369
|
-
if (!
|
|
25370
|
-
|
|
25371
|
-
const name =
|
|
25402
|
+
const el2 = document.querySelector("#project-branch");
|
|
25403
|
+
if (!el2) return;
|
|
25404
|
+
el2.hidden = !branch;
|
|
25405
|
+
const name = el2.querySelector(".project-branch-name");
|
|
25372
25406
|
if (name) name.textContent = branch;
|
|
25373
|
-
|
|
25407
|
+
el2.title = branch ? `Current branch: ${branch}` : "";
|
|
25374
25408
|
}
|
|
25375
25409
|
let metaFilesForViewedProgress = [];
|
|
25376
25410
|
function viewedProgressFor(files) {
|
|
@@ -25487,36 +25521,36 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
25487
25521
|
return true;
|
|
25488
25522
|
}
|
|
25489
25523
|
function renderMeta(meta) {
|
|
25490
|
-
const
|
|
25524
|
+
const el2 = $("#meta");
|
|
25491
25525
|
if (!meta) {
|
|
25492
|
-
|
|
25526
|
+
el2.textContent = "";
|
|
25493
25527
|
metaFilesForViewedProgress = [];
|
|
25494
25528
|
return;
|
|
25495
25529
|
}
|
|
25496
25530
|
setProjectName(meta.project || "");
|
|
25497
25531
|
setProjectBranch(meta.branch || "");
|
|
25498
25532
|
metaFilesForViewedProgress = meta.files || [];
|
|
25499
|
-
|
|
25533
|
+
el2.innerHTML = "";
|
|
25500
25534
|
const text3 = diffText();
|
|
25501
25535
|
if (meta.error) {
|
|
25502
25536
|
const error2 = document.createElement("span");
|
|
25503
25537
|
error2.className = "chip chip-error";
|
|
25504
25538
|
error2.textContent = meta.error;
|
|
25505
|
-
|
|
25539
|
+
el2.appendChild(error2);
|
|
25506
25540
|
}
|
|
25507
25541
|
if (meta.totals) {
|
|
25508
25542
|
const files = document.createElement("span");
|
|
25509
25543
|
files.className = "chip chip-files";
|
|
25510
25544
|
files.textContent = text3.files(meta.totals.files);
|
|
25511
|
-
|
|
25545
|
+
el2.appendChild(files);
|
|
25512
25546
|
const add2 = document.createElement("span");
|
|
25513
25547
|
add2.className = "chip chip-add";
|
|
25514
25548
|
add2.textContent = `+${meta.totals.additions}`;
|
|
25515
|
-
|
|
25549
|
+
el2.appendChild(add2);
|
|
25516
25550
|
const del = document.createElement("span");
|
|
25517
25551
|
del.className = "chip chip-del";
|
|
25518
25552
|
del.textContent = `−${meta.totals.deletions}`;
|
|
25519
|
-
|
|
25553
|
+
el2.appendChild(del);
|
|
25520
25554
|
}
|
|
25521
25555
|
const kinds = summarizeDiffFileKinds(meta.files);
|
|
25522
25556
|
const kindChip = (className, label, count) => {
|
|
@@ -25524,7 +25558,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
25524
25558
|
const chip = document.createElement("span");
|
|
25525
25559
|
chip.className = `chip ${className}`;
|
|
25526
25560
|
chip.textContent = `${count} ${label}`;
|
|
25527
|
-
|
|
25561
|
+
el2.appendChild(chip);
|
|
25528
25562
|
};
|
|
25529
25563
|
kindChip("chip-added", text3.kindAdded, kinds.added);
|
|
25530
25564
|
kindChip("chip-deleted", text3.kindDeleted, kinds.deleted);
|
|
@@ -25542,7 +25576,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
25542
25576
|
viewedProgress.viewed,
|
|
25543
25577
|
viewedProgress.total
|
|
25544
25578
|
);
|
|
25545
|
-
|
|
25579
|
+
el2.appendChild(viewed);
|
|
25546
25580
|
const nextUnviewed = document.createElement("button");
|
|
25547
25581
|
nextUnviewed.type = "button";
|
|
25548
25582
|
nextUnviewed.className = "chip chip-next-unviewed";
|
|
@@ -25553,7 +25587,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
25553
25587
|
nextUnviewed.addEventListener("click", () => {
|
|
25554
25588
|
scrollToNextUnviewedFile();
|
|
25555
25589
|
});
|
|
25556
|
-
|
|
25590
|
+
el2.appendChild(nextUnviewed);
|
|
25557
25591
|
}
|
|
25558
25592
|
const u2 = document.createElement("span");
|
|
25559
25593
|
u2.className = "chip chip-updated";
|
|
@@ -25561,7 +25595,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
25561
25595
|
u2.textContent = text3.updated(
|
|
25562
25596
|
(/* @__PURE__ */ new Date()).toLocaleTimeString([], { hour12: false })
|
|
25563
25597
|
);
|
|
25564
|
-
|
|
25598
|
+
el2.appendChild(u2);
|
|
25565
25599
|
}
|
|
25566
25600
|
let SUPPRESS_SPY_UNTIL = 0;
|
|
25567
25601
|
function prefetchByPath(path) {
|
|
@@ -25683,17 +25717,29 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
25683
25717
|
LOAD_QUEUE.length = 0;
|
|
25684
25718
|
ACTIVE_LOADS = 0;
|
|
25685
25719
|
}
|
|
25686
|
-
function
|
|
25720
|
+
function fileKey2(f2) {
|
|
25687
25721
|
return f2.key || f2.path;
|
|
25688
25722
|
}
|
|
25689
25723
|
function computeListSignature(files) {
|
|
25690
25724
|
return files.map(
|
|
25691
|
-
(f2) => `${
|
|
25725
|
+
(f2) => `${fileKey2(f2)}\0${f2.path}\0${f2.old_path || ""}\0${f2.status || "M"}`
|
|
25692
25726
|
).join("\n");
|
|
25693
25727
|
}
|
|
25728
|
+
function stripLoadUrlGeneration(url) {
|
|
25729
|
+
const queryStart = url.indexOf("?");
|
|
25730
|
+
if (queryStart === -1) return url;
|
|
25731
|
+
const params = new URLSearchParams(url.slice(queryStart + 1));
|
|
25732
|
+
if (!params.has("generation")) return url;
|
|
25733
|
+
params.delete("generation");
|
|
25734
|
+
const s2 = params.toString();
|
|
25735
|
+
return s2 ? `${url.slice(0, queryStart)}?${s2}` : url.slice(0, queryStart);
|
|
25736
|
+
}
|
|
25737
|
+
function diffResponseSignature(data) {
|
|
25738
|
+
return JSON.stringify({ ...data, generation: void 0 });
|
|
25739
|
+
}
|
|
25694
25740
|
function computeCardSignature(f2) {
|
|
25695
25741
|
return [
|
|
25696
|
-
|
|
25742
|
+
fileKey2(f2),
|
|
25697
25743
|
f2.status || "M",
|
|
25698
25744
|
f2.additions || 0,
|
|
25699
25745
|
f2.deletions || 0,
|
|
@@ -25702,12 +25748,18 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
25702
25748
|
f2.size_class || "small",
|
|
25703
25749
|
f2.force_layout || "",
|
|
25704
25750
|
f2.highlight ? 1 : 0,
|
|
25705
|
-
f2.load_url,
|
|
25706
|
-
f2.preview_url
|
|
25751
|
+
stripLoadUrlGeneration(f2.load_url),
|
|
25752
|
+
f2.preview_url ? stripLoadUrlGeneration(f2.preview_url) : "",
|
|
25707
25753
|
f2.estimated_height_px || 0,
|
|
25708
25754
|
f2.untracked ? 1 : 0
|
|
25709
25755
|
].join("\0");
|
|
25710
25756
|
}
|
|
25757
|
+
function cardNeedsLoad(card) {
|
|
25758
|
+
if (card.classList.contains("loading")) return false;
|
|
25759
|
+
if (card.dataset.staleLoading === "1") return false;
|
|
25760
|
+
if (card.classList.contains("loaded")) return card.dataset.stale === "1";
|
|
25761
|
+
return true;
|
|
25762
|
+
}
|
|
25711
25763
|
function ensureLazyObserver() {
|
|
25712
25764
|
if (!lazyObserver) {
|
|
25713
25765
|
lazyObserver = new IntersectionObserver(
|
|
@@ -25715,8 +25767,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
25715
25767
|
for (const entry of entries) {
|
|
25716
25768
|
if (!entry.isIntersecting) continue;
|
|
25717
25769
|
const card = entry.target;
|
|
25718
|
-
if (
|
|
25719
|
-
continue;
|
|
25770
|
+
if (!cardNeedsLoad(card)) continue;
|
|
25720
25771
|
const f2 = card._file || STATE.files.find((x) => x.path === card.dataset.path);
|
|
25721
25772
|
if (f2) enqueueLoad(f2, card, 0);
|
|
25722
25773
|
}
|
|
@@ -25738,15 +25789,27 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
25738
25789
|
return false;
|
|
25739
25790
|
if (!changedPathsCoverPath(changedPaths, file.path)) return false;
|
|
25740
25791
|
card.dataset.reqId = String(++CLIENT_REQ_SEQ);
|
|
25792
|
+
delete card.dataset.stale;
|
|
25793
|
+
delete card.dataset.staleLoading;
|
|
25741
25794
|
card.style.minHeight = `${measuredHeight ?? card.offsetHeight}px`;
|
|
25742
25795
|
card.classList.remove("loaded", "loading", "error");
|
|
25743
25796
|
card.classList.add("pending");
|
|
25744
25797
|
card._diffData = null;
|
|
25798
|
+
card._loadedSig = null;
|
|
25799
|
+
card._loadedSigUrl = null;
|
|
25745
25800
|
const indicator = card.querySelector(".loading-indicator");
|
|
25746
25801
|
if (indicator) indicator.hidden = false;
|
|
25747
25802
|
activatePendingCard(card, file);
|
|
25748
25803
|
return true;
|
|
25749
25804
|
}
|
|
25805
|
+
function revalidateCardSilently(card, file) {
|
|
25806
|
+
if (!card.classList.contains("loaded")) return false;
|
|
25807
|
+
card.dataset.reqId = String(++CLIENT_REQ_SEQ);
|
|
25808
|
+
card.dataset.stale = "1";
|
|
25809
|
+
card._file = file;
|
|
25810
|
+
activatePendingCard(card, file);
|
|
25811
|
+
return true;
|
|
25812
|
+
}
|
|
25750
25813
|
function updateSidebarStats(files) {
|
|
25751
25814
|
for (const f2 of files) {
|
|
25752
25815
|
const li = document.querySelector(
|
|
@@ -25770,15 +25833,19 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
25770
25833
|
const tmp = createPlaceholder(file);
|
|
25771
25834
|
while (tmp.firstChild) card.appendChild(tmp.firstChild);
|
|
25772
25835
|
card.dataset.path = file.path;
|
|
25773
|
-
card.dataset.key =
|
|
25836
|
+
card.dataset.key = fileKey2(file);
|
|
25774
25837
|
card.dataset.sizeClass = file.size_class || "small";
|
|
25775
25838
|
card.dataset.status = file.status || "M";
|
|
25776
25839
|
card.dataset.reqId = String(++CLIENT_REQ_SEQ);
|
|
25777
25840
|
delete card.dataset.manualRendered;
|
|
25778
25841
|
delete card.dataset.manualLoad;
|
|
25779
25842
|
delete card.dataset.manualMode;
|
|
25843
|
+
delete card.dataset.stale;
|
|
25844
|
+
delete card.dataset.staleLoading;
|
|
25780
25845
|
card.style.minHeight = `${file.estimated_height_px || 80}px`;
|
|
25781
25846
|
card._diffData = null;
|
|
25847
|
+
card._loadedSig = null;
|
|
25848
|
+
card._loadedSigUrl = null;
|
|
25782
25849
|
card._file = file;
|
|
25783
25850
|
}
|
|
25784
25851
|
function renderShell(meta, changedPaths) {
|
|
@@ -25793,7 +25860,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
25793
25860
|
renderMeta(meta);
|
|
25794
25861
|
const target = getDiffRoot?.() || $("#diff");
|
|
25795
25862
|
const empty = getEmptyPane?.() || $("#empty");
|
|
25796
|
-
const expectedKeys = newFiles.map(
|
|
25863
|
+
const expectedKeys = newFiles.map(fileKey2);
|
|
25797
25864
|
const domIntact = isDiffShellDomIntact(target, expectedKeys);
|
|
25798
25865
|
const sidebarNeedsRender = shouldRenderDiffSidebar(listSame, domIntact);
|
|
25799
25866
|
if (!newFiles.length) {
|
|
@@ -25817,11 +25884,11 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
25817
25884
|
empty.classList.add("hidden");
|
|
25818
25885
|
const newCardSigs = /* @__PURE__ */ new Map();
|
|
25819
25886
|
for (const f2 of newFiles) {
|
|
25820
|
-
newCardSigs.set(
|
|
25887
|
+
newCardSigs.set(fileKey2(f2), computeCardSignature(f2));
|
|
25821
25888
|
}
|
|
25822
25889
|
const pathsUnknown = !changedPaths;
|
|
25823
25890
|
const contentMayNeedReload = !listSame || pathsUnknown || (changedPaths ? newFiles.some((file) => {
|
|
25824
|
-
const key =
|
|
25891
|
+
const key = fileKey2(file);
|
|
25825
25892
|
return prevCardSignatures.get(key) !== newCardSigs.get(key) || changedPathsCoverPath(changedPaths, file.path);
|
|
25826
25893
|
}) : false);
|
|
25827
25894
|
if (contentMayNeedReload) resetLoadScheduling();
|
|
@@ -25830,14 +25897,14 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
25830
25897
|
const cardsByKey = collectDiffCardsByKey(target);
|
|
25831
25898
|
const measuredHeights = /* @__PURE__ */ new Map();
|
|
25832
25899
|
for (const f2 of newFiles) {
|
|
25833
|
-
const key =
|
|
25900
|
+
const key = fileKey2(f2);
|
|
25834
25901
|
const card = cardsByKey.get(key);
|
|
25835
25902
|
if (card && (card.classList.contains("loaded") || card.classList.contains("loading")))
|
|
25836
25903
|
measuredHeights.set(key, card.offsetHeight);
|
|
25837
25904
|
}
|
|
25838
25905
|
let sidebarNeedsStatsUpdate = false;
|
|
25839
25906
|
for (const f2 of newFiles) {
|
|
25840
|
-
const key =
|
|
25907
|
+
const key = fileKey2(f2);
|
|
25841
25908
|
const oldSig = prevCardSignatures.get(key);
|
|
25842
25909
|
const newSig = newCardSigs.get(key) ?? computeCardSignature(f2);
|
|
25843
25910
|
const sigChanged = oldSig !== newSig;
|
|
@@ -25854,23 +25921,37 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
25854
25921
|
activatePendingCard(card, f2);
|
|
25855
25922
|
invalidatedCards++;
|
|
25856
25923
|
sidebarNeedsStatsUpdate = true;
|
|
25857
|
-
} else {
|
|
25924
|
+
} else if (sigChanged) {
|
|
25858
25925
|
const stats = card.querySelector(".gdp-shell-header .stats");
|
|
25859
25926
|
if (stats) {
|
|
25860
25927
|
stats.innerHTML = '<span class="a">+' + (f2.additions || 0) + '</span><span class="d">−' + (f2.deletions || 0) + "</span>";
|
|
25861
25928
|
}
|
|
25862
25929
|
card._file = f2;
|
|
25863
|
-
const didInvalidate =
|
|
25930
|
+
const didInvalidate = invalidateLoadedCard(
|
|
25864
25931
|
card,
|
|
25865
25932
|
f2,
|
|
25866
|
-
|
|
25933
|
+
null,
|
|
25867
25934
|
measuredHeights.get(key)
|
|
25868
25935
|
);
|
|
25869
25936
|
if (didInvalidate) invalidatedCards++;
|
|
25870
|
-
else if (
|
|
25937
|
+
else if (card.classList.contains("pending")) {
|
|
25871
25938
|
activatePendingCard(card, f2);
|
|
25872
25939
|
}
|
|
25873
|
-
|
|
25940
|
+
sidebarNeedsStatsUpdate = true;
|
|
25941
|
+
} else {
|
|
25942
|
+
card._file = f2;
|
|
25943
|
+
if (!revalidateCardSilently(card, f2)) {
|
|
25944
|
+
const didInvalidate = invalidateLoadedCard(
|
|
25945
|
+
card,
|
|
25946
|
+
f2,
|
|
25947
|
+
changedPaths,
|
|
25948
|
+
measuredHeights.get(key)
|
|
25949
|
+
);
|
|
25950
|
+
if (didInvalidate) invalidatedCards++;
|
|
25951
|
+
else if (card.classList.contains("pending")) {
|
|
25952
|
+
activatePendingCard(card, f2);
|
|
25953
|
+
}
|
|
25954
|
+
}
|
|
25874
25955
|
}
|
|
25875
25956
|
}
|
|
25876
25957
|
if (sidebarNeedsStatsUpdate && canUpdateSidebar)
|
|
@@ -25893,7 +25974,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
25893
25974
|
const oldByKey = collectDiffCardsByKey(target);
|
|
25894
25975
|
const ordered = [];
|
|
25895
25976
|
for (const f2 of newFiles) {
|
|
25896
|
-
const key =
|
|
25977
|
+
const key = fileKey2(f2);
|
|
25897
25978
|
const old = oldByKey.get(key);
|
|
25898
25979
|
if (old) {
|
|
25899
25980
|
oldByKey.delete(key);
|
|
@@ -25965,8 +26046,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
25965
26046
|
entries.forEach((entry) => {
|
|
25966
26047
|
if (!entry.isIntersecting) return;
|
|
25967
26048
|
const card = entry.target;
|
|
25968
|
-
if (
|
|
25969
|
-
return;
|
|
26049
|
+
if (!cardNeedsLoad(card)) return;
|
|
25970
26050
|
const f2 = card._file || STATE.files.find((x) => x.path === card.dataset.path);
|
|
25971
26051
|
if (!f2) return;
|
|
25972
26052
|
enqueueLoad(f2, card, 0);
|
|
@@ -26007,8 +26087,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
26007
26087
|
while (ACTIVE_LOADS < MAX_PARALLEL && LOAD_QUEUE.length) {
|
|
26008
26088
|
const item = LOAD_QUEUE.shift();
|
|
26009
26089
|
if (item.epoch !== LOAD_EPOCH) continue;
|
|
26010
|
-
if (
|
|
26011
|
-
continue;
|
|
26090
|
+
if (!cardNeedsLoad(item.card)) continue;
|
|
26012
26091
|
ACTIVE_LOADS++;
|
|
26013
26092
|
loadFile(item.file, item.card).finally(() => {
|
|
26014
26093
|
if (item.epoch === LOAD_EPOCH) {
|
|
@@ -26103,20 +26182,29 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
26103
26182
|
});
|
|
26104
26183
|
}
|
|
26105
26184
|
function loadFile(file, card, urlOverride, options) {
|
|
26106
|
-
card.classList.
|
|
26107
|
-
card.classList.add("loading");
|
|
26108
|
-
if (lazyObserver) lazyObserver.unobserve(card);
|
|
26185
|
+
const silent = card.classList.contains("loaded") && card.dataset.stale === "1";
|
|
26109
26186
|
const indicator = card.querySelector(".loading-indicator");
|
|
26110
|
-
if (
|
|
26187
|
+
if (silent) {
|
|
26188
|
+
card.dataset.staleLoading = "1";
|
|
26189
|
+
} else {
|
|
26190
|
+
card.classList.remove("pending");
|
|
26191
|
+
card.classList.add("loading");
|
|
26192
|
+
if (indicator) indicator.hidden = false;
|
|
26193
|
+
}
|
|
26194
|
+
if (lazyObserver) lazyObserver.unobserve(card);
|
|
26111
26195
|
const url = urlOverride || (card.dataset.manualMode === "full" ? file.load_url : file.preview_url || file.load_url);
|
|
26112
26196
|
const myGen = getServerGeneration();
|
|
26113
26197
|
const myReq = ++CLIENT_REQ_SEQ;
|
|
26114
26198
|
card.dataset.reqId = String(myReq);
|
|
26115
26199
|
const retryStale = () => {
|
|
26116
26200
|
if (String(myReq) !== card.dataset.reqId) return;
|
|
26117
|
-
|
|
26118
|
-
|
|
26119
|
-
|
|
26201
|
+
if (silent) {
|
|
26202
|
+
delete card.dataset.staleLoading;
|
|
26203
|
+
} else {
|
|
26204
|
+
card.classList.remove("loading");
|
|
26205
|
+
card.classList.add("pending");
|
|
26206
|
+
if (indicator) indicator.hidden = true;
|
|
26207
|
+
}
|
|
26120
26208
|
const fresh = card._file || STATE.files.find((x) => x.path === card.dataset.path);
|
|
26121
26209
|
if (fresh && card.isConnected) enqueueLoad(fresh, card, 0);
|
|
26122
26210
|
};
|
|
@@ -26135,11 +26223,32 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
26135
26223
|
retryStale();
|
|
26136
26224
|
return;
|
|
26137
26225
|
}
|
|
26226
|
+
const strippedUrl = stripLoadUrlGeneration(url);
|
|
26227
|
+
if (silent) {
|
|
26228
|
+
const sig = diffResponseSignature(data);
|
|
26229
|
+
if (card._loadedSigUrl === strippedUrl && card._loadedSig === sig) {
|
|
26230
|
+
delete card.dataset.staleLoading;
|
|
26231
|
+
delete card.dataset.stale;
|
|
26232
|
+
return;
|
|
26233
|
+
}
|
|
26234
|
+
}
|
|
26138
26235
|
if (!options?.immediate) await nextIdle();
|
|
26139
26236
|
if (String(myReq) !== card.dataset.reqId) return;
|
|
26237
|
+
if (silent) {
|
|
26238
|
+
delete card.dataset.staleLoading;
|
|
26239
|
+
delete card.dataset.stale;
|
|
26240
|
+
}
|
|
26241
|
+
card._loadedSig = diffResponseSignature(data);
|
|
26242
|
+
card._loadedSigUrl = strippedUrl;
|
|
26140
26243
|
renderFile(file, data, card);
|
|
26141
26244
|
}).catch((error2) => {
|
|
26142
26245
|
if (String(myReq) !== card.dataset.reqId) return;
|
|
26246
|
+
if (silent) {
|
|
26247
|
+
delete card.dataset.staleLoading;
|
|
26248
|
+
delete card.dataset.stale;
|
|
26249
|
+
console.error("[code-viewer] silent diff revalidation failed", error2);
|
|
26250
|
+
return;
|
|
26251
|
+
}
|
|
26143
26252
|
console.error("[code-viewer] failed to load diff", error2);
|
|
26144
26253
|
card.classList.remove("loading");
|
|
26145
26254
|
card.classList.add("error");
|
|
@@ -26851,7 +26960,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
26851
26960
|
const mount = getMount();
|
|
26852
26961
|
return mount ? !mount.hidden : false;
|
|
26853
26962
|
}
|
|
26854
|
-
async function
|
|
26963
|
+
async function open2() {
|
|
26855
26964
|
const mount = getMount();
|
|
26856
26965
|
if (!mount) return;
|
|
26857
26966
|
bindOnce(mount);
|
|
@@ -26886,7 +26995,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
26886
26995
|
if (!mount) return;
|
|
26887
26996
|
await load(mount);
|
|
26888
26997
|
}
|
|
26889
|
-
return { open, close, isOpen, refresh };
|
|
26998
|
+
return { open: open2, close, isOpen, refresh };
|
|
26890
26999
|
}
|
|
26891
27000
|
|
|
26892
27001
|
// web-src/views/empty-diff-pane.ts
|
|
@@ -27372,12 +27481,12 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
27372
27481
|
if (label) label.textContent = "";
|
|
27373
27482
|
}
|
|
27374
27483
|
function syncRefreshResult(result) {
|
|
27375
|
-
const
|
|
27376
|
-
if (!
|
|
27377
|
-
|
|
27378
|
-
|
|
27379
|
-
|
|
27380
|
-
|
|
27484
|
+
const el2 = result ?? activeMount.refreshResult;
|
|
27485
|
+
if (!el2) return;
|
|
27486
|
+
el2.textContent = "";
|
|
27487
|
+
el2.hidden = true;
|
|
27488
|
+
el2.classList.toggle("changed", false);
|
|
27489
|
+
el2.classList.toggle("pending", false);
|
|
27381
27490
|
}
|
|
27382
27491
|
function syncFilterClearButton(button) {
|
|
27383
27492
|
const clearButton = button ?? activeMount.filterClearButton;
|
|
@@ -27398,8 +27507,8 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
27398
27507
|
}
|
|
27399
27508
|
const gen = generation;
|
|
27400
27509
|
const set2 = (sel, text3) => {
|
|
27401
|
-
const
|
|
27402
|
-
if (
|
|
27510
|
+
const el2 = info.querySelector(sel);
|
|
27511
|
+
if (el2) el2.textContent = text3;
|
|
27403
27512
|
};
|
|
27404
27513
|
info.querySelector(".hci-head")?.removeAttribute("hidden");
|
|
27405
27514
|
set2(".hci-sha", commit.sha);
|
|
@@ -27935,8 +28044,8 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
27935
28044
|
|
|
27936
28045
|
// web-src/views/file-history-shell.ts
|
|
27937
28046
|
function removeFileHistoryShell() {
|
|
27938
|
-
document.querySelectorAll(".gdp-standalone-file-history").forEach((
|
|
27939
|
-
(
|
|
28047
|
+
document.querySelectorAll(".gdp-standalone-file-history").forEach((el2) => {
|
|
28048
|
+
(el2.closest(".gdp-repo-blob-layout") || el2).remove();
|
|
27940
28049
|
});
|
|
27941
28050
|
}
|
|
27942
28051
|
function renderFileHistoryShell(deps, route, options = {}) {
|
|
@@ -28901,6 +29010,31 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
28901
29010
|
}
|
|
28902
29011
|
]
|
|
28903
29012
|
},
|
|
29013
|
+
{
|
|
29014
|
+
title: "Worktrees",
|
|
29015
|
+
blocks: [
|
|
29016
|
+
{
|
|
29017
|
+
kind: "paragraph",
|
|
29018
|
+
text: "The Worktrees item in the header menu lists every worktree of this repository — the main one and every linked worktree — in the same three-pane shape as History: pick a worktree on the left, its changed files in the middle, the diff on the right. Running one coding agent per worktree makes that spread invisible from inside a single checkout, and this screen is where it becomes visible again. The selection lives in the URL (?wt=…&file=…), so a reload comes back to the same diff."
|
|
29019
|
+
},
|
|
29020
|
+
{
|
|
29021
|
+
kind: "paragraph",
|
|
29022
|
+
text: `Every row in the left pane answers two things. How far the branch has drifted from the base branch (how many commits ahead and behind), and whether it still merges: code-viewer runs git merge-tree without touching any working tree, so a row says either that it merges cleanly, or how many files would conflict, or that the check could not run — the last one is kept separate from the first, because "not checked" is not "safe". The middle pane then splits that worktree's files into work that is not committed yet and commits made since the branch point, with added and deleted line counts; the diff itself is rendered by the same viewer the Diff screen uses, from git run inside that worktree.`
|
|
29023
|
+
},
|
|
29024
|
+
{
|
|
29025
|
+
kind: "paragraph",
|
|
29026
|
+
text: "The banner above the cards is the one to read first. It names every file that more than one worktree is currently changing, and the same files are marked inside each card. Two agents editing the same file is invisible until one of them merges; this is where it shows up before that happens. The base branch is whatever origin/HEAD points at, falling back to main and then master; each row names the one it used."
|
|
29027
|
+
},
|
|
29028
|
+
{
|
|
29029
|
+
kind: "paragraph",
|
|
29030
|
+
text: "Create makes a worktree under .worktrees/ in the repository root. You give it a folder name and the dialog shows the exact path it will create as you type; the branch defaults to that same name, so an existing branch is checked out and otherwise a new one starts from where you are. Because that folder sits inside the repository, git reports it as untracked until you add .worktrees/ to .gitignore — the dialog keeps that note behind a ? mark, and code-viewer never edits .gitignore for you. Remove deletes the worktree's folder from disk — the dialog says so, with the full path and a note that it cannot be undone — and keeps the branch and its committed work. With uncommitted changes the dialog also shows a warning and requires a checkbox before it deletes. An entry whose folder is already gone is cleaned from git's bookkeeping instead (git worktree prune), and the dialog says how many such entries will go. Because prune silently skips locked entries and still succeeds, code-viewer checks the entry is actually gone before reporting success and explains why if it is not. The worktree this server is serving cannot be removed from here. Delete sits on its own line, away from the everyday buttons, and stays muted until you reach for it."
|
|
29031
|
+
},
|
|
29032
|
+
{
|
|
29033
|
+
kind: "paragraph",
|
|
29034
|
+
text: 'Every row carries a "…" on the right, and every action for that worktree lives in it — no button appears just because you picked a row, and the row you act on is the row you opened the menu from, whether or not it is the one being shown. "Open in a new tab" starts a second code-viewer for that worktree, because a server stays on the working tree it started in; an already-running server is reused instead of started again. Those servers outlive this one, so "Stop its server" is in the same menu — the Server group in doctor still lists them all, and `kill <pid>` works too, with the pid in ~/.cache/code-viewer/servers/. A worktree that merges cleanly also offers to copy the `git switch` / `git merge` command; code-viewer copies it and never runs it. "Copy its address" is there because a new tab can be stopped by a browser extension before it loads (Chrome reports ERR_BLOCKED_BY_CLIENT) — the address still works in another browser or from a terminal. "Open folder" only appears for worktrees inside the repository, since that is the only place code-viewer will open on your behalf.'
|
|
29035
|
+
}
|
|
29036
|
+
]
|
|
29037
|
+
},
|
|
28904
29038
|
{
|
|
28905
29039
|
title: "Environment doctor",
|
|
28906
29040
|
blocks: [
|
|
@@ -29643,6 +29777,31 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
29643
29777
|
}
|
|
29644
29778
|
]
|
|
29645
29779
|
},
|
|
29780
|
+
{
|
|
29781
|
+
title: "作業ツリー",
|
|
29782
|
+
blocks: [
|
|
29783
|
+
{
|
|
29784
|
+
kind: "paragraph",
|
|
29785
|
+
text: "ヘッダメニューの「作業ツリー」は、このリポジトリの作業ツリーを本体ぶんも含めて並べます。画面の形は履歴と同じ 3 つの列で、左で作業ツリーを選び、中央にその変更ファイル、右に差分が出ます。コーディングエージェントを作業ツリーごとに走らせると、1 つのチェックアウトの中からは全体が見えなくなります。この画面はそれを見えるようにするためのものです。選んだものは URL に載る (?wt=…&file=…) ので、読み込み直しても同じ差分に戻ります。"
|
|
29786
|
+
},
|
|
29787
|
+
{
|
|
29788
|
+
kind: "paragraph",
|
|
29789
|
+
text: "左の 1 行が答えるのは 2 つです。基準ブランチからどれだけ離れているか(進んだぶん・遅れたぶんのコミット数)。そしてまだマージできるか — 作業ツリーを一切触らない git merge-tree で試し、「そのままマージできます」「マージすると何ファイルで衝突するか」「確かめられなかった」を出し分けます。最後のものは 1 番目と混ぜません。「確かめていない」は「安全」ではないからです。中央の列は、その作業ツリーが触っているファイルを、まだコミットしていないぶんと分岐した後のコミットに分けて、追加・削除の行数つきで出します。差分そのものは Diff ビューアと同じ描画で、その作業ツリーの中で走らせた git の結果です。"
|
|
29790
|
+
},
|
|
29791
|
+
{
|
|
29792
|
+
kind: "paragraph",
|
|
29793
|
+
text: "カードの上の帯を最初に読んでください。2 本以上の作業ツリーが今まさに触っているファイルを名指しで挙げ、同じファイルは各カードの中にも印が付きます。2 つのエージェントが同じファイルを書いていることは、どちらかをマージするまで表に出ません。ここはそれが起きる前に出る場所です。基準ブランチは origin/HEAD が指す先で、無ければ main、次に master を使います。どれを使ったかは各行に出ます。"
|
|
29794
|
+
},
|
|
29795
|
+
{
|
|
29796
|
+
kind: "paragraph",
|
|
29797
|
+
text: "「作る」はリポジトリ直下の .worktrees/ の下に作業ツリーを作ります。入力するのはフォルダ名で、打つそばから作られるパスがダイアログに出ます。ブランチは同じ名前が既定で、既にあるブランチならそれを開き、無ければいまの地点から新しく作ります。この置き場所はリポジトリの中なので、.worktrees/ を .gitignore に入れるまでは git から未追跡として見えます。その案内はダイアログの「?」に入れてあり、code-viewer が .gitignore を書き換えることはしません。「削除」はその作業ツリーのフォルダをディスクから消します。ダイアログにはフルパスと「元に戻せません」が出ます。ブランチとコミット済みの内容は残します。コミットしていない変更があるときは警告が出て、チェックを入れないと削除できません。フォルダが既に無い登録は git の管理情報の掃除 (git worktree prune) になり、同じ状態の登録が他にもあれば件数を出します。prune はロックされた登録を黙って飛ばして成功を返すので、消えたことを確かめてから成功と言います (残っていれば理由つきで断ります)。このサーバが映している作業ツリーはここからは消せません。削除だけは他の操作と段を分けて置いてあり、押すまでは沈んだ字で出ます。"
|
|
29798
|
+
},
|
|
29799
|
+
{
|
|
29800
|
+
kind: "paragraph",
|
|
29801
|
+
text: "各行の右端に「…」があり、その作業ツリーへの操作は全部その中にあります。行を選んだからといってボタンが現れることはなく、操作の相手は「…」を開いた行です(いま映している行である必要はありません)。「別タブで見る」はその作業ツリーで code-viewer をもう 1 本起こします。サーバは起動したときの作業ツリーから動けないためです。既に動いているサーバがあれば使い回します。起こしたサーバはこのサーバより長く生きるので、「サーバを止める」を同じメニューに置いてあります。doctor の Server グループには変わらず一覧が出ますし、`kill <pid>` でも止まります(pid は ~/.cache/code-viewer/servers/)。そのままマージできる作業ツリーには、取り込むコマンドのコピーも出ます。コピーするだけで、code-viewer が実行することはありません。「アドレスをコピー」があるのは、開いたタブがブラウザ拡張に止められることがあるためです(Chrome は ERR_BLOCKED_BY_CLIENT と出します)。アドレスさえ手元にあれば、別のブラウザやターミナルから開けます。「フォルダを開く」はリポジトリの中にある作業ツリーにだけ出ます。code-viewer が代わりに開くのはそこまでだからです。"
|
|
29802
|
+
}
|
|
29803
|
+
]
|
|
29804
|
+
},
|
|
29646
29805
|
{
|
|
29647
29806
|
title: "環境ドクター",
|
|
29648
29807
|
blocks: [
|
|
@@ -31810,13 +31969,13 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
31810
31969
|
function clearTaskDropTargets() {
|
|
31811
31970
|
root.querySelectorAll(
|
|
31812
31971
|
".journal-task-card.drop-target, .journal-task-column.drop-target"
|
|
31813
|
-
).forEach((
|
|
31814
|
-
|
|
31972
|
+
).forEach((el2) => {
|
|
31973
|
+
el2.classList.remove("drop-target", "drop-after");
|
|
31815
31974
|
});
|
|
31816
31975
|
}
|
|
31817
31976
|
function clearTaskDragState() {
|
|
31818
|
-
root.querySelectorAll(".journal-task-card.dragging").forEach((
|
|
31819
|
-
|
|
31977
|
+
root.querySelectorAll(".journal-task-card.dragging").forEach((el2) => {
|
|
31978
|
+
el2.classList.remove("dragging");
|
|
31820
31979
|
});
|
|
31821
31980
|
stopTaskDragAutoScroll();
|
|
31822
31981
|
clearTaskDropTargets();
|
|
@@ -33110,7 +33269,7 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
33110
33269
|
fullLink.textContent = text3.viewAll;
|
|
33111
33270
|
settingsLink.textContent = text3.settings;
|
|
33112
33271
|
}
|
|
33113
|
-
function
|
|
33272
|
+
function open2() {
|
|
33114
33273
|
applyText();
|
|
33115
33274
|
renderContent();
|
|
33116
33275
|
popover.hidden = false;
|
|
@@ -33122,7 +33281,7 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
33122
33281
|
}
|
|
33123
33282
|
function toggle() {
|
|
33124
33283
|
if (isOpen()) close();
|
|
33125
|
-
else
|
|
33284
|
+
else open2();
|
|
33126
33285
|
}
|
|
33127
33286
|
trigger.addEventListener("click", toggle);
|
|
33128
33287
|
closeBtn.addEventListener("click", close);
|
|
@@ -33152,7 +33311,7 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
33152
33311
|
applyText();
|
|
33153
33312
|
if (isOpen()) renderContent();
|
|
33154
33313
|
}
|
|
33155
|
-
return { open, close, toggle, isOpen, localize };
|
|
33314
|
+
return { open: open2, close, toggle, isOpen, localize };
|
|
33156
33315
|
}
|
|
33157
33316
|
|
|
33158
33317
|
// web-src/views/ref-picker.ts
|
|
@@ -33669,9 +33828,9 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
33669
33828
|
syncSidebarHeaderHeight();
|
|
33670
33829
|
}
|
|
33671
33830
|
let SIDEBAR_FILES = [];
|
|
33672
|
-
function setFolderIcon(
|
|
33831
|
+
function setFolderIcon(el2, collapsed) {
|
|
33673
33832
|
const path = collapsed ? FOLDER_ICON_PATHS.closed : FOLDER_ICON_PATHS.open;
|
|
33674
|
-
|
|
33833
|
+
el2.innerHTML = '<svg class="octicon octicon-file-directory-' + (collapsed ? "fill" : "open-fill") + '" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" aria-hidden="true"><path fill="currentColor" d="' + path + '"></path></svg>';
|
|
33675
33834
|
}
|
|
33676
33835
|
function setSidebarTreeActionIcons() {
|
|
33677
33836
|
const sidebarToggle = ensureSidebarToggleButton();
|
|
@@ -34281,13 +34440,13 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
34281
34440
|
input2.toggleAttribute("aria-invalid", invalid);
|
|
34282
34441
|
input2.title = invalid ? filter.error || "invalid regular expression" : "";
|
|
34283
34442
|
const filterActive = filter.kind !== "empty" && !invalid;
|
|
34284
|
-
const
|
|
34443
|
+
const matches2 = invalid ? () => true : filter.match;
|
|
34285
34444
|
const walk = (node, depth) => {
|
|
34286
34445
|
let subtreeVisible = false;
|
|
34287
34446
|
const rows = [];
|
|
34288
34447
|
for (const item of treeNodeItems(node)) {
|
|
34289
34448
|
if (item.kind === "dir") {
|
|
34290
|
-
const dirMatches = filterActive &&
|
|
34449
|
+
const dirMatches = filterActive && matches2(item.dir.path);
|
|
34291
34450
|
const eff = dirEffectiveCollapsed(item.dir);
|
|
34292
34451
|
const expanded = !item.dir.children_omitted && !eff.lazyNotLoaded && (filterActive ? !eff.userCollapsed : !eff.effectiveCollapsed);
|
|
34293
34452
|
const child = walk(item.dir, depth + 1);
|
|
@@ -34305,7 +34464,7 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
34305
34464
|
subtreeVisible = subtreeVisible || visible;
|
|
34306
34465
|
} else {
|
|
34307
34466
|
const testHidden = STATE.hideTests && !isRepositorySidebarMode() && isTestPath(item.file.path || "");
|
|
34308
|
-
const visible = !testHidden &&
|
|
34467
|
+
const visible = !testHidden && matches2(item.file.path || "");
|
|
34309
34468
|
if (visible) {
|
|
34310
34469
|
rows.push({
|
|
34311
34470
|
kind: "file",
|
|
@@ -34703,19 +34862,19 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
34703
34862
|
const invalid = filter.kind === "invalid";
|
|
34704
34863
|
input2.toggleAttribute("aria-invalid", invalid);
|
|
34705
34864
|
input2.title = invalid ? filter.error || "invalid regular expression" : "";
|
|
34706
|
-
const
|
|
34865
|
+
const matches2 = invalid ? () => true : filter.match;
|
|
34707
34866
|
const filterActive = filter.kind !== "empty" && !invalid;
|
|
34708
34867
|
$$("#filelist li[data-path]").forEach((li) => {
|
|
34709
|
-
const match2 =
|
|
34868
|
+
const match2 = matches2(li.dataset.path || "");
|
|
34710
34869
|
li.classList.toggle("hidden", !match2);
|
|
34711
34870
|
});
|
|
34712
34871
|
if (!isRepositorySidebarMode()) {
|
|
34713
34872
|
document.querySelectorAll(".gdp-file-shell").forEach((card) => {
|
|
34714
|
-
const match2 =
|
|
34873
|
+
const match2 = matches2(card.dataset.path || "");
|
|
34715
34874
|
card.classList.toggle("hidden-by-filter", !match2);
|
|
34716
34875
|
});
|
|
34717
34876
|
}
|
|
34718
|
-
updateTreeDirVisibility(
|
|
34877
|
+
updateTreeDirVisibility(matches2, filterActive);
|
|
34719
34878
|
if (!isRepositorySidebarMode() && typeof applyViewedState === "function")
|
|
34720
34879
|
applyViewedState();
|
|
34721
34880
|
}
|
|
@@ -34769,6 +34928,7 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
34769
34928
|
const input2 = document.querySelector("#sb-filter");
|
|
34770
34929
|
if (!input2?.value) return;
|
|
34771
34930
|
input2.value = "";
|
|
34931
|
+
input2.dispatchEvent(new Event("input", { bubbles: true }));
|
|
34772
34932
|
syncSidebarFilterClearButton();
|
|
34773
34933
|
flushSidebarFilter();
|
|
34774
34934
|
applyFilter();
|
|
@@ -36012,6 +36172,7 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
36012
36172
|
async function loadRawFileInfo(target) {
|
|
36013
36173
|
try {
|
|
36014
36174
|
const res = await fetch(buildRawFileUrl(target), { method: "HEAD" });
|
|
36175
|
+
if (res.status === 404) return { missing: true };
|
|
36015
36176
|
if (!res.ok) return {};
|
|
36016
36177
|
const rawSize = res.headers.get("content-length");
|
|
36017
36178
|
const size = rawSize == null ? NaN : Number(rawSize);
|
|
@@ -37242,11 +37403,11 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
37242
37403
|
const grouped = /* @__PURE__ */ new Map();
|
|
37243
37404
|
state.items.forEach((item, index) => {
|
|
37244
37405
|
if (item.kind !== "grep") return;
|
|
37245
|
-
const
|
|
37246
|
-
|
|
37247
|
-
grouped.set(item.path,
|
|
37406
|
+
const matches2 = grouped.get(item.path) ?? [];
|
|
37407
|
+
matches2.push({ item, index });
|
|
37408
|
+
grouped.set(item.path, matches2);
|
|
37248
37409
|
});
|
|
37249
|
-
for (const [path,
|
|
37410
|
+
for (const [path, matches2] of grouped) {
|
|
37250
37411
|
const group = document.createElement("section");
|
|
37251
37412
|
group.className = "gdp-palette-file-group";
|
|
37252
37413
|
group.setAttribute("role", "group");
|
|
@@ -37259,11 +37420,11 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
37259
37420
|
name.title = path;
|
|
37260
37421
|
const count = document.createElement("span");
|
|
37261
37422
|
count.className = "gdp-palette-file-heading-count";
|
|
37262
|
-
count.textContent = String(
|
|
37423
|
+
count.textContent = String(matches2.length);
|
|
37263
37424
|
heading2.append(name, count);
|
|
37264
37425
|
const rows = document.createElement("div");
|
|
37265
37426
|
rows.className = "gdp-palette-file-matches";
|
|
37266
|
-
for (const match2 of
|
|
37427
|
+
for (const match2 of matches2) {
|
|
37267
37428
|
rows.appendChild(
|
|
37268
37429
|
createPaletteRow(state, match2.item, match2.index, true)
|
|
37269
37430
|
);
|
|
@@ -38028,11 +38189,11 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
38028
38189
|
return STATE.route.screen === "file" ? { path: STATE.route.path, ref: STATE.route.ref } : null;
|
|
38029
38190
|
}
|
|
38030
38191
|
function removeStandaloneSource() {
|
|
38031
|
-
document.querySelectorAll(".gdp-standalone-source").forEach((
|
|
38032
|
-
|
|
38192
|
+
document.querySelectorAll(".gdp-standalone-source").forEach((el2) => {
|
|
38193
|
+
el2.remove();
|
|
38033
38194
|
});
|
|
38034
|
-
document.querySelectorAll(".gdp-repo-blob-layout").forEach((
|
|
38035
|
-
|
|
38195
|
+
document.querySelectorAll(".gdp-repo-blob-layout").forEach((el2) => {
|
|
38196
|
+
el2.remove();
|
|
38036
38197
|
});
|
|
38037
38198
|
}
|
|
38038
38199
|
function renderSourceLoading(card, target, onCancel) {
|
|
@@ -38598,17 +38759,17 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
38598
38759
|
return ranges;
|
|
38599
38760
|
}
|
|
38600
38761
|
function collectVirtualSourceSearchMatches(lines, query, max = 5e3) {
|
|
38601
|
-
const
|
|
38602
|
-
for (let index = 0; index < lines.length &&
|
|
38762
|
+
const matches2 = [];
|
|
38763
|
+
for (let index = 0; index < lines.length && matches2.length < max; index++) {
|
|
38603
38764
|
for (const range of virtualSourceSearchRanges(
|
|
38604
38765
|
lines[index] || "",
|
|
38605
38766
|
query
|
|
38606
38767
|
)) {
|
|
38607
|
-
|
|
38608
|
-
if (
|
|
38768
|
+
matches2.push({ line: index + 1, start: range.start, end: range.end });
|
|
38769
|
+
if (matches2.length >= max) break;
|
|
38609
38770
|
}
|
|
38610
38771
|
}
|
|
38611
|
-
return
|
|
38772
|
+
return matches2;
|
|
38612
38773
|
}
|
|
38613
38774
|
function appendVirtualSourceLineCode(code2, line, query, activeRange, lineNumber) {
|
|
38614
38775
|
const ranges = virtualSourceSearchRanges(line, query);
|
|
@@ -38652,7 +38813,7 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
38652
38813
|
bar.append(input2, count, previous, next, close);
|
|
38653
38814
|
wrap.querySelector(".gdp-source-virtual-info")?.appendChild(bar);
|
|
38654
38815
|
bar.hidden = true;
|
|
38655
|
-
let
|
|
38816
|
+
let matches2 = [];
|
|
38656
38817
|
let active = -1;
|
|
38657
38818
|
let debounce = 0;
|
|
38658
38819
|
let searchVersion = 0;
|
|
@@ -38665,7 +38826,7 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
38665
38826
|
const query = input2.value;
|
|
38666
38827
|
const version = ++searchVersion;
|
|
38667
38828
|
if (!query) {
|
|
38668
|
-
|
|
38829
|
+
matches2 = [];
|
|
38669
38830
|
active = -1;
|
|
38670
38831
|
count.textContent = "";
|
|
38671
38832
|
renderFn();
|
|
@@ -38674,20 +38835,20 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
38674
38835
|
count.textContent = "Searching...";
|
|
38675
38836
|
findMatches(query).then((nextMatches) => {
|
|
38676
38837
|
if (version !== searchVersion) return;
|
|
38677
|
-
|
|
38678
|
-
active =
|
|
38679
|
-
count.textContent =
|
|
38838
|
+
matches2 = nextMatches;
|
|
38839
|
+
active = matches2.length ? Math.max(0, Math.min(active, matches2.length - 1)) : -1;
|
|
38840
|
+
count.textContent = matches2.length ? `${active + 1} / ${matches2.length}` : "0 / 0";
|
|
38680
38841
|
if (active >= 0) {
|
|
38681
38842
|
const rowHeight = sourceLineScrollAmount() || VIRTUAL_SOURCE_ROW_HEIGHT;
|
|
38682
38843
|
scroller.scrollTop = Math.max(
|
|
38683
38844
|
0,
|
|
38684
|
-
(
|
|
38845
|
+
(matches2[active].line - 1) * rowHeight - rowHeight * 3
|
|
38685
38846
|
);
|
|
38686
38847
|
}
|
|
38687
38848
|
renderFn();
|
|
38688
38849
|
}).catch(() => {
|
|
38689
38850
|
if (version !== searchVersion) return;
|
|
38690
|
-
|
|
38851
|
+
matches2 = [];
|
|
38691
38852
|
active = -1;
|
|
38692
38853
|
count.textContent = "Search failed";
|
|
38693
38854
|
renderFn();
|
|
@@ -38698,13 +38859,13 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
38698
38859
|
debounce = window.setTimeout(sync, 120);
|
|
38699
38860
|
};
|
|
38700
38861
|
const move = (direction) => {
|
|
38701
|
-
if (!
|
|
38702
|
-
active = (active + direction +
|
|
38703
|
-
count.textContent = `${active + 1} / ${
|
|
38862
|
+
if (!matches2.length) return;
|
|
38863
|
+
active = (active + direction + matches2.length) % matches2.length;
|
|
38864
|
+
count.textContent = `${active + 1} / ${matches2.length}`;
|
|
38704
38865
|
const rowHeight = sourceLineScrollAmount() || VIRTUAL_SOURCE_ROW_HEIGHT;
|
|
38705
38866
|
scroller.scrollTop = Math.max(
|
|
38706
38867
|
0,
|
|
38707
|
-
(
|
|
38868
|
+
(matches2[active].line - 1) * rowHeight - rowHeight * 3
|
|
38708
38869
|
);
|
|
38709
38870
|
renderFn();
|
|
38710
38871
|
};
|
|
@@ -38733,7 +38894,7 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
38733
38894
|
sync();
|
|
38734
38895
|
},
|
|
38735
38896
|
query: () => bar.hidden ? "" : input2.value,
|
|
38736
|
-
activeRange: () => active >= 0 ?
|
|
38897
|
+
activeRange: () => active >= 0 ? matches2[active] || null : null
|
|
38737
38898
|
};
|
|
38738
38899
|
}
|
|
38739
38900
|
function openVirtualSourceSearchFromKeyboard(targetEl) {
|
|
@@ -39100,10 +39261,10 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
39100
39261
|
scroller.__gdpRenderVirtualSource = render;
|
|
39101
39262
|
scroller.addEventListener("scroll", schedule, { passive: true });
|
|
39102
39263
|
const findPagedMatches = async (query, matchSignal) => {
|
|
39103
|
-
const
|
|
39264
|
+
const matches2 = [];
|
|
39104
39265
|
let startLine = 1;
|
|
39105
39266
|
let done = false;
|
|
39106
|
-
while (!done &&
|
|
39267
|
+
while (!done && matches2.length < 5e3) {
|
|
39107
39268
|
const endLine = startLine + VIRTUAL_SOURCE_PAGE_SIZE - 1;
|
|
39108
39269
|
const data = await trackLoad(
|
|
39109
39270
|
fetch(buildFileRangeUrl(target, startLine, endLine), {
|
|
@@ -39118,12 +39279,12 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
39118
39279
|
const lineNumber = data.start + index;
|
|
39119
39280
|
lines.set(lineNumber, lineValue);
|
|
39120
39281
|
for (const range of virtualSourceSearchRanges(lineValue, query)) {
|
|
39121
|
-
|
|
39282
|
+
matches2.push({
|
|
39122
39283
|
line: lineNumber,
|
|
39123
39284
|
start: range.start,
|
|
39124
39285
|
end: range.end
|
|
39125
39286
|
});
|
|
39126
|
-
if (
|
|
39287
|
+
if (matches2.length >= 5e3) break;
|
|
39127
39288
|
}
|
|
39128
39289
|
});
|
|
39129
39290
|
totalRows = data.complete ? Math.max(1, data.total) : Math.max(totalRows, data.total, endLine + VIRTUAL_SOURCE_PAGE_SIZE);
|
|
@@ -39135,7 +39296,7 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
39135
39296
|
renderedStart = -1;
|
|
39136
39297
|
renderedEnd = -1;
|
|
39137
39298
|
schedule();
|
|
39138
|
-
return
|
|
39299
|
+
return matches2;
|
|
39139
39300
|
};
|
|
39140
39301
|
search = createVirtualSourceSearch(
|
|
39141
39302
|
wrap,
|
|
@@ -39313,8 +39474,8 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
39313
39474
|
const repoTarget = repoFileTargetFromRoute();
|
|
39314
39475
|
setPageMode();
|
|
39315
39476
|
removeStandaloneSource();
|
|
39316
|
-
document.querySelectorAll(".gdp-repo-blob-layout").forEach((
|
|
39317
|
-
|
|
39477
|
+
document.querySelectorAll(".gdp-repo-blob-layout").forEach((el2) => {
|
|
39478
|
+
el2.remove();
|
|
39318
39479
|
});
|
|
39319
39480
|
const card = document.createElement("article");
|
|
39320
39481
|
card.className = "gdp-file-shell loaded gdp-standalone-source gdp-source-mode";
|
|
@@ -39785,13 +39946,13 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
39785
39946
|
}
|
|
39786
39947
|
|
|
39787
39948
|
// web-src/core/scroll-chaining.ts
|
|
39788
|
-
function hasScrollRoom(
|
|
39789
|
-
const up = event.deltaY < 0 &&
|
|
39790
|
-
const down = event.deltaY > 0 &&
|
|
39791
|
-
const left = event.deltaX < 0 &&
|
|
39792
|
-
const right = event.deltaX > 0 &&
|
|
39949
|
+
function hasScrollRoom(el2, event) {
|
|
39950
|
+
const up = event.deltaY < 0 && el2.scrollTop > 1;
|
|
39951
|
+
const down = event.deltaY > 0 && el2.scrollHeight - el2.clientHeight - el2.scrollTop > 1;
|
|
39952
|
+
const left = event.deltaX < 0 && el2.scrollLeft > 1;
|
|
39953
|
+
const right = event.deltaX > 0 && el2.scrollWidth - el2.clientWidth - el2.scrollLeft > 1;
|
|
39793
39954
|
if (!up && !down && !left && !right) return false;
|
|
39794
|
-
const style = getComputedStyle(
|
|
39955
|
+
const style = getComputedStyle(el2);
|
|
39795
39956
|
const scrollsY = style.overflowY === "auto" || style.overflowY === "scroll";
|
|
39796
39957
|
const scrollsX = style.overflowX === "auto" || style.overflowX === "scroll";
|
|
39797
39958
|
return (up || down) && scrollsY || (left || right) && scrollsX;
|
|
@@ -39999,8 +40160,8 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
39999
40160
|
return parts.join(BRANCH_KEY_SEP);
|
|
40000
40161
|
}
|
|
40001
40162
|
function createSessionBoard(deps) {
|
|
40002
|
-
const
|
|
40003
|
-
|
|
40163
|
+
const el2 = document.createElement("div");
|
|
40164
|
+
el2.className = "terminal-board";
|
|
40004
40165
|
const scopeBar = document.createElement("div");
|
|
40005
40166
|
scopeBar.className = "terminal-scope";
|
|
40006
40167
|
const scopeSelect = document.createElement("select");
|
|
@@ -40043,7 +40204,7 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
40043
40204
|
tree.role = "tree";
|
|
40044
40205
|
const treeEmpty = document.createElement("p");
|
|
40045
40206
|
treeEmpty.className = "terminal-empty";
|
|
40046
|
-
|
|
40207
|
+
el2.append(scopeBar, observationErrors, attentionSection, filters, tree);
|
|
40047
40208
|
let data = {
|
|
40048
40209
|
panes: null,
|
|
40049
40210
|
shells: [],
|
|
@@ -40116,12 +40277,12 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
40116
40277
|
}
|
|
40117
40278
|
const actions = document.createElement("div");
|
|
40118
40279
|
actions.className = "terminal-card-actions";
|
|
40119
|
-
const
|
|
40120
|
-
|
|
40121
|
-
|
|
40122
|
-
|
|
40123
|
-
|
|
40124
|
-
actions.appendChild(
|
|
40280
|
+
const open2 = document.createElement("button");
|
|
40281
|
+
open2.type = "button";
|
|
40282
|
+
open2.className = `terminal-card-open terminal-card-open-${row.state}`;
|
|
40283
|
+
open2.textContent = text3.openTarget;
|
|
40284
|
+
open2.addEventListener("click", () => activate(row));
|
|
40285
|
+
actions.appendChild(open2);
|
|
40125
40286
|
if (row.state === "done") {
|
|
40126
40287
|
const read = document.createElement("button");
|
|
40127
40288
|
read.type = "button";
|
|
@@ -40415,7 +40576,7 @@ ${error2.stack}` : ""}`;
|
|
|
40415
40576
|
}
|
|
40416
40577
|
render();
|
|
40417
40578
|
return {
|
|
40418
|
-
el,
|
|
40579
|
+
el: el2,
|
|
40419
40580
|
setData(next) {
|
|
40420
40581
|
data = next;
|
|
40421
40582
|
render();
|
|
@@ -40471,17 +40632,17 @@ ${error2.stack}` : ""}`;
|
|
|
40471
40632
|
previouslyFocused?.focus?.();
|
|
40472
40633
|
};
|
|
40473
40634
|
const button = (label, title2, onClick) => {
|
|
40474
|
-
const
|
|
40475
|
-
|
|
40476
|
-
|
|
40477
|
-
|
|
40478
|
-
|
|
40479
|
-
|
|
40480
|
-
|
|
40635
|
+
const el2 = document.createElement("button");
|
|
40636
|
+
el2.type = "button";
|
|
40637
|
+
el2.className = "terminal-font-btn";
|
|
40638
|
+
el2.textContent = label;
|
|
40639
|
+
el2.title = title2;
|
|
40640
|
+
el2.setAttribute("aria-label", title2);
|
|
40641
|
+
el2.addEventListener("click", (event) => {
|
|
40481
40642
|
event.stopPropagation();
|
|
40482
40643
|
onClick();
|
|
40483
40644
|
});
|
|
40484
|
-
return
|
|
40645
|
+
return el2;
|
|
40485
40646
|
};
|
|
40486
40647
|
zoomReset = button("100%", text3.zoomReset, () => viewport.reset());
|
|
40487
40648
|
actions.append(
|
|
@@ -40536,14 +40697,14 @@ ${error2.stack}` : ""}`;
|
|
|
40536
40697
|
var INLINE_IMAGE_COLS = 30;
|
|
40537
40698
|
var INLINE_IMAGE_ROWS = 8;
|
|
40538
40699
|
function createTerminalScreen(deps) {
|
|
40539
|
-
const
|
|
40540
|
-
|
|
40700
|
+
const el2 = document.createElement("div");
|
|
40701
|
+
el2.className = "terminal-pane-body";
|
|
40541
40702
|
const attachments = document.createElement("div");
|
|
40542
40703
|
attachments.className = "terminal-attachments";
|
|
40543
40704
|
attachments.hidden = true;
|
|
40544
40705
|
const screenEl = document.createElement("div");
|
|
40545
40706
|
screenEl.className = "terminal-screen";
|
|
40546
|
-
|
|
40707
|
+
el2.append(attachments, screenEl);
|
|
40547
40708
|
let term = null;
|
|
40548
40709
|
let fitAddon = null;
|
|
40549
40710
|
let source = null;
|
|
@@ -40664,13 +40825,13 @@ ${formatErrorDetail(error2)}`
|
|
|
40664
40825
|
function addAttachment(src, name, path) {
|
|
40665
40826
|
const item = document.createElement("div");
|
|
40666
40827
|
item.className = "terminal-attachment";
|
|
40667
|
-
const
|
|
40668
|
-
|
|
40669
|
-
|
|
40828
|
+
const open2 = document.createElement("button");
|
|
40829
|
+
open2.type = "button";
|
|
40830
|
+
open2.className = "terminal-attachment-open";
|
|
40670
40831
|
const openLabel = deps.getText().openImage;
|
|
40671
|
-
|
|
40672
|
-
|
|
40673
|
-
|
|
40832
|
+
open2.title = path;
|
|
40833
|
+
open2.setAttribute("aria-label", `${openLabel}: ${name}`);
|
|
40834
|
+
open2.addEventListener("click", () => {
|
|
40674
40835
|
openImageLightbox({ url: src, name, path }, deps.getText());
|
|
40675
40836
|
});
|
|
40676
40837
|
const image2 = document.createElement("img");
|
|
@@ -40688,7 +40849,7 @@ ${formatErrorDetail(error2)}`
|
|
|
40688
40849
|
);
|
|
40689
40850
|
}
|
|
40690
40851
|
});
|
|
40691
|
-
|
|
40852
|
+
open2.appendChild(image2);
|
|
40692
40853
|
const label = document.createElement("span");
|
|
40693
40854
|
label.className = "terminal-attachment-name";
|
|
40694
40855
|
label.textContent = name;
|
|
@@ -40703,7 +40864,7 @@ ${formatErrorDetail(error2)}`
|
|
|
40703
40864
|
item.remove();
|
|
40704
40865
|
attachments.hidden = attachments.childElementCount === 0;
|
|
40705
40866
|
});
|
|
40706
|
-
item.append(
|
|
40867
|
+
item.append(open2, label, remove);
|
|
40707
40868
|
attachments.appendChild(item);
|
|
40708
40869
|
attachments.hidden = false;
|
|
40709
40870
|
}
|
|
@@ -40928,7 +41089,7 @@ ${formatErrorDetail(error2)}`
|
|
|
40928
41089
|
}
|
|
40929
41090
|
return null;
|
|
40930
41091
|
}
|
|
40931
|
-
|
|
41092
|
+
el2.addEventListener(
|
|
40932
41093
|
"paste",
|
|
40933
41094
|
(event) => {
|
|
40934
41095
|
const file = firstImage(event.clipboardData);
|
|
@@ -41080,7 +41241,7 @@ ${formatErrorDetail(error2)}`
|
|
|
41080
41241
|
deps.onStatus(null);
|
|
41081
41242
|
}
|
|
41082
41243
|
return {
|
|
41083
|
-
el,
|
|
41244
|
+
el: el2,
|
|
41084
41245
|
applyFontSize() {
|
|
41085
41246
|
if (!term) return;
|
|
41086
41247
|
term.options.fontSize = deps.getFontSize();
|
|
@@ -41562,7 +41723,7 @@ ${formatErrorDetail(error2)}`);
|
|
|
41562
41723
|
const host = getMount();
|
|
41563
41724
|
return host ? !host.hidden : false;
|
|
41564
41725
|
}
|
|
41565
|
-
async function
|
|
41726
|
+
async function open2(id) {
|
|
41566
41727
|
const host = getMount();
|
|
41567
41728
|
if (!host || disposed) return;
|
|
41568
41729
|
const myGen = ++generation;
|
|
@@ -41621,7 +41782,7 @@ ${formatErrorDetail(error2)}`);
|
|
|
41621
41782
|
renderLists();
|
|
41622
41783
|
}
|
|
41623
41784
|
return {
|
|
41624
|
-
open,
|
|
41785
|
+
open: open2,
|
|
41625
41786
|
close,
|
|
41626
41787
|
isOpen,
|
|
41627
41788
|
getActiveTarget: () => attached?.id ?? lastTargetId,
|
|
@@ -41772,8 +41933,8 @@ ${formatErrorDetail(error2)}`);
|
|
|
41772
41933
|
}
|
|
41773
41934
|
function createScratchpadPane(text3, outputTitle, placeholder, options) {
|
|
41774
41935
|
let currentText = text3;
|
|
41775
|
-
const
|
|
41776
|
-
|
|
41936
|
+
const el2 = document.createElement("div");
|
|
41937
|
+
el2.className = `tools-pane ${options.toolClassName}`;
|
|
41777
41938
|
const inputSide = document.createElement("section");
|
|
41778
41939
|
inputSide.className = "tools-pane-side tools-pane-input";
|
|
41779
41940
|
const { head: inputHead, titleEl: inputTitle } = createHead(text3.pane.input);
|
|
@@ -41808,7 +41969,7 @@ ${formatErrorDetail(error2)}`);
|
|
|
41808
41969
|
const output = document.createElement("div");
|
|
41809
41970
|
output.className = "tools-pane-body";
|
|
41810
41971
|
outputSide.append(outputHead, output);
|
|
41811
|
-
|
|
41972
|
+
el2.append(inputSide, resizer, outputSide);
|
|
41812
41973
|
let statusTimer = null;
|
|
41813
41974
|
let pinnedStatus = null;
|
|
41814
41975
|
let normalStatus = { message: "", tone: "info" };
|
|
@@ -41888,21 +42049,21 @@ ${formatErrorDetail(error2)}`);
|
|
|
41888
42049
|
});
|
|
41889
42050
|
const MIN_SIDE_WIDTH = 220;
|
|
41890
42051
|
function applyInputWidth(width) {
|
|
41891
|
-
const total =
|
|
42052
|
+
const total = el2.getBoundingClientRect().width;
|
|
41892
42053
|
const max = Math.max(MIN_SIDE_WIDTH, total - MIN_SIDE_WIDTH);
|
|
41893
42054
|
const clamped = Math.max(MIN_SIDE_WIDTH, Math.min(max, width));
|
|
41894
|
-
|
|
42055
|
+
el2.style.setProperty("--tools-input-width", `${Math.round(clamped)}px`);
|
|
41895
42056
|
}
|
|
41896
42057
|
const detachResizer = attachDragResizer({
|
|
41897
42058
|
handle: resizer,
|
|
41898
42059
|
getSize: () => inputSide.getBoundingClientRect().width,
|
|
41899
42060
|
applySize: applyInputWidth,
|
|
41900
42061
|
direction: 1,
|
|
41901
|
-
activeClassTarget:
|
|
42062
|
+
activeClassTarget: el2,
|
|
41902
42063
|
activeClassName: "tools-pane-resizing"
|
|
41903
42064
|
});
|
|
41904
42065
|
return {
|
|
41905
|
-
el,
|
|
42066
|
+
el: el2,
|
|
41906
42067
|
input: input2,
|
|
41907
42068
|
output,
|
|
41908
42069
|
setStatus,
|
|
@@ -42426,7 +42587,7 @@ ${formatErrorDetail(error2)}`);
|
|
|
42426
42587
|
const host = getMount();
|
|
42427
42588
|
return host ? !host.hidden : false;
|
|
42428
42589
|
}
|
|
42429
|
-
async function
|
|
42590
|
+
async function open2(tool) {
|
|
42430
42591
|
const host = getMount();
|
|
42431
42592
|
if (!host) return;
|
|
42432
42593
|
const myGen = ++generation;
|
|
@@ -42483,7 +42644,7 @@ ${formatErrorDetail(error2)}`);
|
|
|
42483
42644
|
};
|
|
42484
42645
|
window.addEventListener("beforeunload", onBeforeUnload);
|
|
42485
42646
|
return {
|
|
42486
|
-
open,
|
|
42647
|
+
open: open2,
|
|
42487
42648
|
close,
|
|
42488
42649
|
isOpen,
|
|
42489
42650
|
getActiveTool: () => activeTool,
|
|
@@ -43137,6 +43298,1704 @@ ${formatErrorDetail(error2)}`);
|
|
|
43137
43298
|
return { mount, sync, localize };
|
|
43138
43299
|
}
|
|
43139
43300
|
|
|
43301
|
+
// web-src/views/worktree-i18n.ts
|
|
43302
|
+
var EN_STATUS_TITLES = {
|
|
43303
|
+
M: "modified",
|
|
43304
|
+
A: "added",
|
|
43305
|
+
D: "deleted",
|
|
43306
|
+
R: "renamed",
|
|
43307
|
+
C: "copied",
|
|
43308
|
+
U: "untracked"
|
|
43309
|
+
};
|
|
43310
|
+
var JA_STATUS_TITLES = {
|
|
43311
|
+
M: "変更",
|
|
43312
|
+
A: "追加",
|
|
43313
|
+
D: "削除",
|
|
43314
|
+
R: "リネーム",
|
|
43315
|
+
C: "コピー",
|
|
43316
|
+
U: "未追跡"
|
|
43317
|
+
};
|
|
43318
|
+
var TEXT3 = {
|
|
43319
|
+
en: {
|
|
43320
|
+
title: "Worktrees",
|
|
43321
|
+
ariaLabel: "Git worktrees",
|
|
43322
|
+
loading: "Loading worktrees…",
|
|
43323
|
+
loadFailed: "Failed to load worktrees.",
|
|
43324
|
+
empty: "No worktrees.",
|
|
43325
|
+
refresh: "Reload",
|
|
43326
|
+
refreshTitle: "Reload the worktree list",
|
|
43327
|
+
count: (n2) => n2 === 1 ? "1 worktree" : `${n2} worktrees`,
|
|
43328
|
+
baseUnknown: "no base branch found",
|
|
43329
|
+
gitignoreHint: "Git sees that directory as untracked. Add .worktrees/ to .gitignore to keep it out of git status.",
|
|
43330
|
+
badges: {
|
|
43331
|
+
current: "this folder",
|
|
43332
|
+
currentTitle: "This code-viewer is serving this folder",
|
|
43333
|
+
detached: "no branch",
|
|
43334
|
+
detachedTitle: "Not attached to any branch (detached HEAD)",
|
|
43335
|
+
bare: "bare",
|
|
43336
|
+
bareTitle: "A storage-only repository with no working files",
|
|
43337
|
+
locked: "locked",
|
|
43338
|
+
prunable: "stale entry",
|
|
43339
|
+
prunableTitle: "Only the git entry remains (e.g. the folder is gone)",
|
|
43340
|
+
missing: "folder is gone",
|
|
43341
|
+
running: "running",
|
|
43342
|
+
runningTitle: "A code-viewer for this folder is running on another port"
|
|
43343
|
+
},
|
|
43344
|
+
diverge: {
|
|
43345
|
+
ahead: (n2, base2) => n2 === 1 ? `1 commit ahead of ${base2}` : `${n2} commits ahead of ${base2}`,
|
|
43346
|
+
behind: (n2, base2) => n2 === 1 ? `1 commit behind ${base2}` : `${n2} commits behind ${base2}`,
|
|
43347
|
+
even: (base2) => `same point as ${base2}`,
|
|
43348
|
+
notComparable: "not compared"
|
|
43349
|
+
},
|
|
43350
|
+
merge: {
|
|
43351
|
+
clean: "merges cleanly",
|
|
43352
|
+
conflict: (n2) => n2 === 1 ? "1 file would conflict on merge" : `${n2} files would conflict on merge`,
|
|
43353
|
+
unknown: "could not check the merge",
|
|
43354
|
+
conflictListLabel: "Conflicting files"
|
|
43355
|
+
},
|
|
43356
|
+
files: {
|
|
43357
|
+
heading: (n2) => n2 === 1 ? "1 changed file" : `${n2} changed files`,
|
|
43358
|
+
none: "No changes.",
|
|
43359
|
+
uncommitted: "Not committed yet",
|
|
43360
|
+
committed: "Committed, not merged",
|
|
43361
|
+
truncated: (shown, total) => `showing ${shown} of ${total}`,
|
|
43362
|
+
// 行の中に置くので短くする。誰と重なっているかは title に入る。
|
|
43363
|
+
overlapMark: "shared",
|
|
43364
|
+
overlapTitle: (others) => `Also changed in: ${others.join(", ")}`,
|
|
43365
|
+
statusTitles: EN_STATUS_TITLES
|
|
43366
|
+
},
|
|
43367
|
+
overlaps: {
|
|
43368
|
+
heading: (n2) => n2 === 1 ? "1 file is touched by more than one worktree" : `${n2} files are touched by more than one worktree`,
|
|
43369
|
+
intro: "Merging one of them will make the others conflict on these files.",
|
|
43370
|
+
entry: (path, worktrees) => `${path} — ${worktrees.join(", ")}`
|
|
43371
|
+
},
|
|
43372
|
+
panes: {
|
|
43373
|
+
worktrees: "Worktrees",
|
|
43374
|
+
files: "Files",
|
|
43375
|
+
diff: "Diff",
|
|
43376
|
+
filterWorktrees: "Filter worktrees…",
|
|
43377
|
+
filterFiles: "Filter files…",
|
|
43378
|
+
noWorktreeMatch: "No worktree matches.",
|
|
43379
|
+
noFileMatch: "No file matches.",
|
|
43380
|
+
selectWorktree: "Pick a worktree to see what it is changing.",
|
|
43381
|
+
selectFile: "Pick a file to see its diff.",
|
|
43382
|
+
diffLoading: "Loading the diff…",
|
|
43383
|
+
diffEmpty: "No textual diff (binary, or the file is unchanged).",
|
|
43384
|
+
diffFailed: "Failed to load the diff.",
|
|
43385
|
+
diffTruncated: (shown, total) => `showing ${shown} of ${total} hunks — open the worktree in a new tab for the whole file`
|
|
43386
|
+
},
|
|
43387
|
+
noCommit: "no commit",
|
|
43388
|
+
lastTouched: (when) => `updated ${when}`,
|
|
43389
|
+
actions: {
|
|
43390
|
+
menuTitle: "Actions for this worktree",
|
|
43391
|
+
menuFor: (name) => `Actions for ${name}`,
|
|
43392
|
+
openFolder: "Open folder",
|
|
43393
|
+
openFolderTitle: "Open this folder in the OS file manager",
|
|
43394
|
+
openFolderFailed: "Could not open that folder.",
|
|
43395
|
+
copyPath: "Copy path",
|
|
43396
|
+
copyPathTitle: "Copy the path to this folder",
|
|
43397
|
+
copyFailed: "Could not copy to the clipboard.",
|
|
43398
|
+
stopServer: "Stop its server",
|
|
43399
|
+
stopServerTitle: "Stop the code-viewer running for this folder",
|
|
43400
|
+
stopFailed: "Failed to stop the server.",
|
|
43401
|
+
copyServerUrl: "Copy its address",
|
|
43402
|
+
copyServerUrlTitle: (url) => `Copy ${url}`,
|
|
43403
|
+
copyMerge: "Copy merge command",
|
|
43404
|
+
copyMergeTitle: (base2, branch) => `Copy the command that merges ${branch} into ${base2}`
|
|
43405
|
+
},
|
|
43406
|
+
emptyDiff: {
|
|
43407
|
+
title: "No changes yet.",
|
|
43408
|
+
body: (path) => `Edit files in ${path} and the diffs will show up here.`
|
|
43409
|
+
},
|
|
43410
|
+
intro: {
|
|
43411
|
+
cardTitle: "What is a worktree?",
|
|
43412
|
+
cardWhat: "A worktree (git worktree) is a second checkout of this repository, in a separate folder on a separate branch.",
|
|
43413
|
+
cardWhy: "Keep main open here while a bugfix branch stays open over there — no branch switching, no stashing.",
|
|
43414
|
+
cardHow: 'When you click "Create": a new folder appears at .worktrees/<name>, with the branch checked out in it. Edit files there as usual. The changes show up on this screen as diffs.',
|
|
43415
|
+
cardButton: "Create a worktree",
|
|
43416
|
+
listNote: "This is the only folder right now. New worktrees will appear here.",
|
|
43417
|
+
overlapLegend: "⇄ = another worktree is changing this file too"
|
|
43418
|
+
},
|
|
43419
|
+
open: "Open in a new tab",
|
|
43420
|
+
openTitle: "Start a code-viewer for this folder and open it in a new tab",
|
|
43421
|
+
opening: "Starting…",
|
|
43422
|
+
openFailed: "Failed to open this worktree.",
|
|
43423
|
+
add: "Create",
|
|
43424
|
+
addTitle: "Create a new worktree",
|
|
43425
|
+
addFailed: "Failed to create the worktree.",
|
|
43426
|
+
addDialog: {
|
|
43427
|
+
title: "Create a worktree",
|
|
43428
|
+
intro: "Work on two things side by side, in separate folders, without switching branches.",
|
|
43429
|
+
nameLabel: "Folder name",
|
|
43430
|
+
namePlaceholder: "feature-x",
|
|
43431
|
+
branchLabel: "Branch",
|
|
43432
|
+
branchPlaceholder: "same as the folder name",
|
|
43433
|
+
branchHint: "An existing branch name opens that branch. Otherwise a new one starts from where you are now.",
|
|
43434
|
+
targetLabel: "Creates",
|
|
43435
|
+
targetPending: (parent) => `${parent}/…`,
|
|
43436
|
+
gitignoreLabel: "About this folder and git status",
|
|
43437
|
+
submit: "Create"
|
|
43438
|
+
},
|
|
43439
|
+
remove: "Delete this worktree",
|
|
43440
|
+
removeTitle: "Delete this worktree and its folder",
|
|
43441
|
+
removeDialog: {
|
|
43442
|
+
title: "Delete worktree",
|
|
43443
|
+
body: (name) => `Delete the worktree "${name}"?`,
|
|
43444
|
+
diskNote: (path) => `The folder ${path} and everything in it will be deleted from disk. This cannot be undone.`,
|
|
43445
|
+
branchNote: (branch) => `The branch ${branch} and its committed work are kept.`,
|
|
43446
|
+
dirtyNote: (count) => count === 1 ? "1 file has uncommitted changes." : `${count} files have uncommitted changes.`,
|
|
43447
|
+
dirtyLose: "Deleting the worktree will lose them.",
|
|
43448
|
+
force: "Delete even with uncommitted changes",
|
|
43449
|
+
forceRequired: "To delete it anyway, check the box first.",
|
|
43450
|
+
missingBody: (name) => `Remove the entry for "${name}"?`,
|
|
43451
|
+
missingNote: "Its folder is already gone from disk; only the git entry is removed.",
|
|
43452
|
+
lockedNote: "This entry is locked, so git will leave it in place. Unlock it first.",
|
|
43453
|
+
missingOthers: (n2) => n2 === 1 ? "1 other entry whose folder is gone will be cleaned up at the same time." : `${n2} other entries whose folders are gone will be cleaned up at the same time.`,
|
|
43454
|
+
submit: "Delete"
|
|
43455
|
+
},
|
|
43456
|
+
removeFailed: "Failed to delete the worktree.",
|
|
43457
|
+
cancel: "Cancel",
|
|
43458
|
+
nameErrors: {
|
|
43459
|
+
empty: "Enter a name.",
|
|
43460
|
+
control: "Control characters cannot be used.",
|
|
43461
|
+
separator: "Path separators cannot be used.",
|
|
43462
|
+
relative: "This name is not allowed.",
|
|
43463
|
+
"leading-dot": "The name cannot start with a dot.",
|
|
43464
|
+
"too-long": "The name is too long."
|
|
43465
|
+
}
|
|
43466
|
+
},
|
|
43467
|
+
ja: {
|
|
43468
|
+
title: "作業ツリー",
|
|
43469
|
+
ariaLabel: "git の作業ツリー",
|
|
43470
|
+
loading: "作業ツリーを読み込んでいます…",
|
|
43471
|
+
loadFailed: "作業ツリーを読み込めませんでした。",
|
|
43472
|
+
empty: "作業ツリーがありません。",
|
|
43473
|
+
refresh: "再読み込み",
|
|
43474
|
+
refreshTitle: "一覧を読み直す",
|
|
43475
|
+
count: (n2) => `${n2} 本`,
|
|
43476
|
+
baseUnknown: "比較の基準になるブランチが見つかりません",
|
|
43477
|
+
gitignoreHint: "このディレクトリは git から未追跡に見えます。.worktrees/ を .gitignore に入れると git status に出なくなります。",
|
|
43478
|
+
badges: {
|
|
43479
|
+
current: "このフォルダ",
|
|
43480
|
+
currentTitle: "この code-viewer が開いているフォルダです",
|
|
43481
|
+
detached: "ブランチなし",
|
|
43482
|
+
detachedTitle: "どのブランチにも紐づいていません(detached HEAD)",
|
|
43483
|
+
bare: "bare",
|
|
43484
|
+
bareTitle: "作業ファイルを持たない保管用のリポジトリです",
|
|
43485
|
+
locked: "ロック中",
|
|
43486
|
+
prunable: "掃除できます",
|
|
43487
|
+
prunableTitle: "フォルダが無い等で管理情報だけ残っています",
|
|
43488
|
+
missing: "フォルダがありません",
|
|
43489
|
+
running: "起動中",
|
|
43490
|
+
runningTitle: "このフォルダ専用の code-viewer が別ポートで動いています"
|
|
43491
|
+
},
|
|
43492
|
+
diverge: {
|
|
43493
|
+
ahead: (n2, base2) => `${base2} より ${n2} コミット進んでいます`,
|
|
43494
|
+
behind: (n2, base2) => `${base2} より ${n2} コミット遅れています`,
|
|
43495
|
+
even: (base2) => `${base2} と同じ地点です`,
|
|
43496
|
+
notComparable: "比較なし"
|
|
43497
|
+
},
|
|
43498
|
+
merge: {
|
|
43499
|
+
clean: "そのままマージできます",
|
|
43500
|
+
conflict: (n2) => `マージすると ${n2} ファイルで衝突します`,
|
|
43501
|
+
unknown: "マージできるか確かめられませんでした",
|
|
43502
|
+
conflictListLabel: "衝突するファイル"
|
|
43503
|
+
},
|
|
43504
|
+
files: {
|
|
43505
|
+
heading: (n2) => `変更 ${n2} 件`,
|
|
43506
|
+
none: "変更はありません。",
|
|
43507
|
+
uncommitted: "未コミット",
|
|
43508
|
+
committed: "コミット済み・未マージ",
|
|
43509
|
+
truncated: (shown, total) => `${total} 件のうち ${shown} 件を表示`,
|
|
43510
|
+
// 行の中に置くので短くする。誰と重なっているかは title に入る。
|
|
43511
|
+
overlapMark: "重複",
|
|
43512
|
+
overlapTitle: (others) => `同じファイルを触っている: ${others.join("、")}`,
|
|
43513
|
+
statusTitles: JA_STATUS_TITLES
|
|
43514
|
+
},
|
|
43515
|
+
overlaps: {
|
|
43516
|
+
heading: (n2) => `${n2} 個のファイルを 2 本以上が触っています`,
|
|
43517
|
+
intro: "どれか 1 本をマージすると、残りはこのファイルで衝突します。",
|
|
43518
|
+
entry: (path, worktrees) => `${path} — ${worktrees.join("、")}`
|
|
43519
|
+
},
|
|
43520
|
+
panes: {
|
|
43521
|
+
worktrees: "作業ツリー",
|
|
43522
|
+
files: "ファイル",
|
|
43523
|
+
diff: "差分",
|
|
43524
|
+
filterWorktrees: "作業ツリーを絞り込み…",
|
|
43525
|
+
filterFiles: "ファイルを絞り込み…",
|
|
43526
|
+
noWorktreeMatch: "該当する作業ツリーがありません。",
|
|
43527
|
+
noFileMatch: "該当するファイルがありません。",
|
|
43528
|
+
selectWorktree: "作業ツリーを選ぶと、何を触っているかが出ます。",
|
|
43529
|
+
selectFile: "ファイルを選ぶと差分が出ます。",
|
|
43530
|
+
diffLoading: "差分を読み込んでいます…",
|
|
43531
|
+
diffEmpty: "テキストの差分はありません(バイナリか、変更なし)。",
|
|
43532
|
+
diffFailed: "差分を読み込めませんでした。",
|
|
43533
|
+
diffTruncated: (shown, total) => `${total} 個のうち ${shown} 個のかたまりを表示しています。全部見るには、その作業ツリーを別タブで見てください`
|
|
43534
|
+
},
|
|
43535
|
+
noCommit: "コミットなし",
|
|
43536
|
+
lastTouched: (when) => `最終更新 ${when}`,
|
|
43537
|
+
actions: {
|
|
43538
|
+
menuTitle: "この作業ツリーへの操作",
|
|
43539
|
+
menuFor: (name) => `${name} への操作`,
|
|
43540
|
+
openFolder: "フォルダを開く",
|
|
43541
|
+
openFolderTitle: "このフォルダをファイルマネージャで開きます",
|
|
43542
|
+
openFolderFailed: "そのフォルダを開けませんでした。",
|
|
43543
|
+
copyPath: "パスをコピー",
|
|
43544
|
+
copyPathTitle: "このフォルダの場所をコピーします",
|
|
43545
|
+
copyFailed: "クリップボードにコピーできませんでした。",
|
|
43546
|
+
stopServer: "サーバを止める",
|
|
43547
|
+
stopServerTitle: "このフォルダで動いている code-viewer を止めます",
|
|
43548
|
+
stopFailed: "サーバを止められませんでした。",
|
|
43549
|
+
copyServerUrl: "アドレスをコピー",
|
|
43550
|
+
copyServerUrlTitle: (url) => `${url} をコピーします`,
|
|
43551
|
+
copyMerge: "マージのコマンドをコピー",
|
|
43552
|
+
copyMergeTitle: (base2, branch) => `${branch} を ${base2} に取り込むコマンドをコピーします`
|
|
43553
|
+
},
|
|
43554
|
+
emptyDiff: {
|
|
43555
|
+
title: "まだ変更はありません。",
|
|
43556
|
+
body: (path) => `${path} でファイルを編集すると、ここに差分が出ます。`
|
|
43557
|
+
},
|
|
43558
|
+
intro: {
|
|
43559
|
+
cardTitle: "作業ツリー(git worktree)とは",
|
|
43560
|
+
cardWhat: "同じリポジトリを、ブランチを切り替えずに別フォルダでもう 1 つ開く仕組みです。",
|
|
43561
|
+
cardWhy: "main で作業しながら、別フォルダで修正用のブランチを開いておけます。2 つの作業を並べて進められます。",
|
|
43562
|
+
cardHow: "「作る」を押すと .worktrees/〈名前〉 にフォルダができ、指定したブランチがそこに展開されます。あとはそのフォルダで普通に編集してください。変更はこの画面に差分として出ます。",
|
|
43563
|
+
cardButton: "作業ツリーを作る",
|
|
43564
|
+
listNote: "いまはこのフォルダだけです。作業ツリーを作ると、ここに並びます。",
|
|
43565
|
+
overlapLegend: "⇄ = 他の作業ツリーも同じファイルを触っている"
|
|
43566
|
+
},
|
|
43567
|
+
open: "別タブで見る",
|
|
43568
|
+
openTitle: "このフォルダ専用の code-viewer を起動して新しいタブで開きます",
|
|
43569
|
+
opening: "起動中…",
|
|
43570
|
+
openFailed: "この作業ツリーを開けませんでした。",
|
|
43571
|
+
add: "作る",
|
|
43572
|
+
addTitle: "作業ツリーを新しく作る",
|
|
43573
|
+
addFailed: "作業ツリーを作れませんでした。",
|
|
43574
|
+
addDialog: {
|
|
43575
|
+
title: "作業ツリーを作る",
|
|
43576
|
+
intro: "ブランチを切り替えずに、別フォルダで 2 つの作業を並べて進められます。",
|
|
43577
|
+
nameLabel: "フォルダ名",
|
|
43578
|
+
namePlaceholder: "feature-x",
|
|
43579
|
+
branchLabel: "ブランチ",
|
|
43580
|
+
branchPlaceholder: "フォルダ名と同じ",
|
|
43581
|
+
branchHint: "既にあるブランチ名ならそれを開きます。無ければ、いまの地点から新しく作ります。",
|
|
43582
|
+
targetLabel: "作成先",
|
|
43583
|
+
targetPending: (parent) => `${parent}/…`,
|
|
43584
|
+
gitignoreLabel: "このフォルダと git status について",
|
|
43585
|
+
submit: "作る"
|
|
43586
|
+
},
|
|
43587
|
+
remove: "この作業ツリーを削除",
|
|
43588
|
+
removeTitle: "この作業ツリーをフォルダごと削除します",
|
|
43589
|
+
removeDialog: {
|
|
43590
|
+
title: "作業ツリーの削除",
|
|
43591
|
+
body: (name) => `作業ツリー「${name}」を削除しますか。`,
|
|
43592
|
+
diskNote: (path) => `フォルダ ${path} とその中身はディスクから消えます。元に戻せません。`,
|
|
43593
|
+
branchNote: (branch) => `ブランチ ${branch} と、コミット済みの内容は残ります。`,
|
|
43594
|
+
dirtyNote: (count) => `コミットしていない変更が ${count} 件あります。`,
|
|
43595
|
+
dirtyLose: "削除するとこれらの変更は失われます。",
|
|
43596
|
+
force: "変更が残っていても削除する",
|
|
43597
|
+
forceRequired: "変更を捨てて削除するには、チェックを入れてください。",
|
|
43598
|
+
missingBody: (name) => `作業ツリー「${name}」の登録を消しますか。`,
|
|
43599
|
+
missingNote: "フォルダは既にディスク上にありません。git の管理情報だけを消します。",
|
|
43600
|
+
lockedNote: "この登録はロックされているので、git はそのまま残します。先にロックを外してください。",
|
|
43601
|
+
missingOthers: (n2) => `フォルダが無くなっている他の登録 ${n2} 件も、同時に整理されます。`,
|
|
43602
|
+
submit: "削除する"
|
|
43603
|
+
},
|
|
43604
|
+
removeFailed: "作業ツリーを削除できませんでした。",
|
|
43605
|
+
cancel: "キャンセル",
|
|
43606
|
+
nameErrors: {
|
|
43607
|
+
empty: "名前を入力してください。",
|
|
43608
|
+
control: "制御文字は使えません。",
|
|
43609
|
+
separator: "パス区切りは使えません。",
|
|
43610
|
+
relative: "この名前は使えません。",
|
|
43611
|
+
"leading-dot": "ドットで始まる名前は使えません。",
|
|
43612
|
+
"too-long": "名前が長すぎます。"
|
|
43613
|
+
}
|
|
43614
|
+
}
|
|
43615
|
+
};
|
|
43616
|
+
function worktreeText(lang) {
|
|
43617
|
+
return TEXT3[lang];
|
|
43618
|
+
}
|
|
43619
|
+
|
|
43620
|
+
// web-src/core/worktree.ts
|
|
43621
|
+
var WORKTREE_NAME_MAX_LENGTH = 100;
|
|
43622
|
+
function worktreeNameError(name) {
|
|
43623
|
+
if (!name) return "empty";
|
|
43624
|
+
if (name.length > WORKTREE_NAME_MAX_LENGTH) return "too-long";
|
|
43625
|
+
for (const ch of name) {
|
|
43626
|
+
const code2 = ch.charCodeAt(0);
|
|
43627
|
+
if (code2 < 32 || code2 === 127) return "control";
|
|
43628
|
+
}
|
|
43629
|
+
if (name.includes("/") || name.includes("\\")) return "separator";
|
|
43630
|
+
if (name === "." || name === "..") return "relative";
|
|
43631
|
+
if (name.startsWith(".")) return "leading-dot";
|
|
43632
|
+
return null;
|
|
43633
|
+
}
|
|
43634
|
+
function worktreeBranchError(branch) {
|
|
43635
|
+
if (!branch) return "empty";
|
|
43636
|
+
if (branch.length > WORKTREE_NAME_MAX_LENGTH) return "too-long";
|
|
43637
|
+
for (const ch of branch) {
|
|
43638
|
+
const code2 = ch.charCodeAt(0);
|
|
43639
|
+
if (code2 < 32 || code2 === 127) return "control";
|
|
43640
|
+
}
|
|
43641
|
+
if (branch.startsWith("-") || branch.includes("..")) return "relative";
|
|
43642
|
+
return null;
|
|
43643
|
+
}
|
|
43644
|
+
|
|
43645
|
+
// web-src/views/context-menu.ts
|
|
43646
|
+
var open = null;
|
|
43647
|
+
function closeContextMenu() {
|
|
43648
|
+
if (!open) return;
|
|
43649
|
+
const closing = open;
|
|
43650
|
+
open = null;
|
|
43651
|
+
closing.cleanup();
|
|
43652
|
+
closing.element.remove();
|
|
43653
|
+
}
|
|
43654
|
+
function showContextMenu(anchor, items) {
|
|
43655
|
+
closeContextMenu();
|
|
43656
|
+
const menu = document.createElement("div");
|
|
43657
|
+
menu.className = "gdp-context-menu";
|
|
43658
|
+
menu.setAttribute("role", "menu");
|
|
43659
|
+
for (const item of items) {
|
|
43660
|
+
if (item.kind === "separator") {
|
|
43661
|
+
const line = document.createElement("hr");
|
|
43662
|
+
line.className = "gdp-context-menu-sep";
|
|
43663
|
+
menu.appendChild(line);
|
|
43664
|
+
continue;
|
|
43665
|
+
}
|
|
43666
|
+
const button = document.createElement("button");
|
|
43667
|
+
button.type = "button";
|
|
43668
|
+
button.setAttribute("role", "menuitem");
|
|
43669
|
+
button.textContent = item.label;
|
|
43670
|
+
if (item.title) button.title = item.title;
|
|
43671
|
+
if (item.danger) button.classList.add("danger");
|
|
43672
|
+
button.disabled = !!item.disabled;
|
|
43673
|
+
button.addEventListener("click", () => {
|
|
43674
|
+
closeContextMenu();
|
|
43675
|
+
item.onSelect();
|
|
43676
|
+
});
|
|
43677
|
+
menu.appendChild(button);
|
|
43678
|
+
}
|
|
43679
|
+
document.body.appendChild(menu);
|
|
43680
|
+
const rect = menu.getBoundingClientRect();
|
|
43681
|
+
const from = anchor.getBoundingClientRect();
|
|
43682
|
+
const left = Math.min(
|
|
43683
|
+
from.right - rect.width,
|
|
43684
|
+
window.innerWidth - rect.width - 8
|
|
43685
|
+
);
|
|
43686
|
+
const top = Math.min(from.bottom + 4, window.innerHeight - rect.height - 8);
|
|
43687
|
+
menu.style.left = `${Math.max(8, left)}px`;
|
|
43688
|
+
menu.style.top = `${Math.max(8, top)}px`;
|
|
43689
|
+
const onPointerDown = (event) => {
|
|
43690
|
+
if (menu.contains(event.target)) return;
|
|
43691
|
+
closeContextMenu();
|
|
43692
|
+
};
|
|
43693
|
+
const onKeyDown = (event) => {
|
|
43694
|
+
if (event.key !== "Escape") return;
|
|
43695
|
+
event.stopPropagation();
|
|
43696
|
+
closeContextMenu();
|
|
43697
|
+
anchor.focus();
|
|
43698
|
+
};
|
|
43699
|
+
const onScroll = () => closeContextMenu();
|
|
43700
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
43701
|
+
document.addEventListener("keydown", onKeyDown, true);
|
|
43702
|
+
window.addEventListener("scroll", onScroll, true);
|
|
43703
|
+
window.addEventListener("resize", onScroll);
|
|
43704
|
+
open = {
|
|
43705
|
+
element: menu,
|
|
43706
|
+
cleanup() {
|
|
43707
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
43708
|
+
document.removeEventListener("keydown", onKeyDown, true);
|
|
43709
|
+
window.removeEventListener("scroll", onScroll, true);
|
|
43710
|
+
window.removeEventListener("resize", onScroll);
|
|
43711
|
+
}
|
|
43712
|
+
};
|
|
43713
|
+
menu.querySelector("button:not(:disabled)")?.focus();
|
|
43714
|
+
}
|
|
43715
|
+
|
|
43716
|
+
// web-src/views/worktree-view.ts
|
|
43717
|
+
var SSE_REFRESH_DELAY_MS = 400;
|
|
43718
|
+
var DIFF_PREFETCH_MARGIN = "600px";
|
|
43719
|
+
var ACTION_HEADERS = {
|
|
43720
|
+
"Content-Type": "application/json",
|
|
43721
|
+
"X-Code-Viewer-Action": "1"
|
|
43722
|
+
};
|
|
43723
|
+
async function postWorktreeAction(path, body) {
|
|
43724
|
+
const res = await fetch(path, {
|
|
43725
|
+
method: "POST",
|
|
43726
|
+
headers: ACTION_HEADERS,
|
|
43727
|
+
body: JSON.stringify(body)
|
|
43728
|
+
});
|
|
43729
|
+
if (!res.ok) throw new Error(await res.text() || `${res.status}`);
|
|
43730
|
+
return await res.json();
|
|
43731
|
+
}
|
|
43732
|
+
function el(tag, className, text3) {
|
|
43733
|
+
const node = document.createElement(tag);
|
|
43734
|
+
if (className) node.className = className;
|
|
43735
|
+
if (text3 !== void 0) node.textContent = text3;
|
|
43736
|
+
return node;
|
|
43737
|
+
}
|
|
43738
|
+
function fileKey(file) {
|
|
43739
|
+
return `${file.origin}:${file.path}`;
|
|
43740
|
+
}
|
|
43741
|
+
function chevronSvg() {
|
|
43742
|
+
return iconSvg("octicon-chevron-down", CHEVRON_DOWN_16_PATH);
|
|
43743
|
+
}
|
|
43744
|
+
function folderSvg(collapsed) {
|
|
43745
|
+
return iconSvg(
|
|
43746
|
+
collapsed ? "octicon-file-directory-fill" : "octicon-file-directory-open-fill",
|
|
43747
|
+
collapsed ? FOLDER_ICON_PATHS.closed : FOLDER_ICON_PATHS.open
|
|
43748
|
+
);
|
|
43749
|
+
}
|
|
43750
|
+
function matches(haystack, needle) {
|
|
43751
|
+
return !needle || haystack.toLowerCase().includes(needle.toLowerCase());
|
|
43752
|
+
}
|
|
43753
|
+
function createWorktreeView(deps) {
|
|
43754
|
+
let mounted = false;
|
|
43755
|
+
let lifecycle = 0;
|
|
43756
|
+
let acceptedServerGeneration = 0;
|
|
43757
|
+
let data = null;
|
|
43758
|
+
let message = "";
|
|
43759
|
+
let messageIsError = false;
|
|
43760
|
+
let busyPath = "";
|
|
43761
|
+
let sseTimer = null;
|
|
43762
|
+
let refreshRequested = false;
|
|
43763
|
+
let refreshLoop = null;
|
|
43764
|
+
let worktreeFilter = "";
|
|
43765
|
+
let fileFilter = "";
|
|
43766
|
+
let diffFor = null;
|
|
43767
|
+
let restoredRouteKey = null;
|
|
43768
|
+
let observer = null;
|
|
43769
|
+
const listPanel = document.getElementById("worktree-panel");
|
|
43770
|
+
function text3() {
|
|
43771
|
+
return deps.getText();
|
|
43772
|
+
}
|
|
43773
|
+
function route() {
|
|
43774
|
+
const current = deps.getRoute();
|
|
43775
|
+
return current.screen === "worktree" ? current : null;
|
|
43776
|
+
}
|
|
43777
|
+
function setMessage(next, isError = false) {
|
|
43778
|
+
message = next;
|
|
43779
|
+
messageIsError = isError;
|
|
43780
|
+
}
|
|
43781
|
+
function isCurrent(seq) {
|
|
43782
|
+
return mounted && seq === lifecycle && route() !== null;
|
|
43783
|
+
}
|
|
43784
|
+
const worktreeFilterInput = (() => {
|
|
43785
|
+
const input2 = el("input", "history-filter");
|
|
43786
|
+
input2.type = "search";
|
|
43787
|
+
input2.autocomplete = "off";
|
|
43788
|
+
input2.addEventListener("input", () => {
|
|
43789
|
+
worktreeFilter = input2.value;
|
|
43790
|
+
renderList();
|
|
43791
|
+
});
|
|
43792
|
+
return input2;
|
|
43793
|
+
})();
|
|
43794
|
+
function sidebarFilter() {
|
|
43795
|
+
return document.querySelector("#sb-filter");
|
|
43796
|
+
}
|
|
43797
|
+
function onSidebarFilter() {
|
|
43798
|
+
fileFilter = sidebarFilter()?.value || "";
|
|
43799
|
+
renderFiles();
|
|
43800
|
+
}
|
|
43801
|
+
function onSidebarViewToggle() {
|
|
43802
|
+
window.setTimeout(() => renderFiles(), 0);
|
|
43803
|
+
}
|
|
43804
|
+
function setAllDirsCollapsed(collapsed) {
|
|
43805
|
+
const list2 = document.getElementById("filelist");
|
|
43806
|
+
if (!list2) return;
|
|
43807
|
+
for (const dir of list2.querySelectorAll(".tree-dir")) {
|
|
43808
|
+
dir.classList.toggle("collapsed", collapsed);
|
|
43809
|
+
const icon = dir.querySelector(":scope > .dir-icon");
|
|
43810
|
+
if (icon) icon.innerHTML = folderSvg(collapsed);
|
|
43811
|
+
}
|
|
43812
|
+
}
|
|
43813
|
+
function onExpandAll() {
|
|
43814
|
+
setAllDirsCollapsed(false);
|
|
43815
|
+
}
|
|
43816
|
+
function onCollapseAll() {
|
|
43817
|
+
setAllDirsCollapsed(true);
|
|
43818
|
+
}
|
|
43819
|
+
function sidebarViewButtons() {
|
|
43820
|
+
return Array.from(
|
|
43821
|
+
document.querySelectorAll(".sb-view-seg button")
|
|
43822
|
+
);
|
|
43823
|
+
}
|
|
43824
|
+
function mount() {
|
|
43825
|
+
if (mounted || !listPanel) return;
|
|
43826
|
+
document.getElementById("empty")?.classList.add("hidden");
|
|
43827
|
+
document.getElementById("history-commit-info")?.setAttribute("hidden", "true");
|
|
43828
|
+
listPanel.hidden = false;
|
|
43829
|
+
mounted = true;
|
|
43830
|
+
document.body.classList.add("gdp-worktree-page");
|
|
43831
|
+
sidebarFilter()?.addEventListener("input", onSidebarFilter);
|
|
43832
|
+
document.getElementById("filelist")?.addEventListener("click", onFileListClick);
|
|
43833
|
+
for (const button of sidebarViewButtons()) {
|
|
43834
|
+
button.addEventListener("click", onSidebarViewToggle);
|
|
43835
|
+
}
|
|
43836
|
+
document.getElementById("sb-expand-all")?.addEventListener("click", onExpandAll);
|
|
43837
|
+
document.getElementById("sb-collapse-all")?.addEventListener("click", onCollapseAll);
|
|
43838
|
+
deps.setPageMode();
|
|
43839
|
+
deps.syncHeaderMenu();
|
|
43840
|
+
}
|
|
43841
|
+
function suspend() {
|
|
43842
|
+
lifecycle++;
|
|
43843
|
+
closeContextMenu();
|
|
43844
|
+
observer?.disconnect();
|
|
43845
|
+
observer = null;
|
|
43846
|
+
diffFor = null;
|
|
43847
|
+
restoredRouteKey = null;
|
|
43848
|
+
if (sseTimer !== null) {
|
|
43849
|
+
window.clearTimeout(sseTimer);
|
|
43850
|
+
sseTimer = null;
|
|
43851
|
+
}
|
|
43852
|
+
refreshRequested = false;
|
|
43853
|
+
if (listPanel) {
|
|
43854
|
+
listPanel.hidden = true;
|
|
43855
|
+
listPanel.replaceChildren();
|
|
43856
|
+
}
|
|
43857
|
+
sidebarFilter()?.removeEventListener("input", onSidebarFilter);
|
|
43858
|
+
document.getElementById("filelist")?.removeEventListener("click", onFileListClick);
|
|
43859
|
+
for (const button of sidebarViewButtons()) {
|
|
43860
|
+
button.removeEventListener("click", onSidebarViewToggle);
|
|
43861
|
+
}
|
|
43862
|
+
document.getElementById("sb-expand-all")?.removeEventListener("click", onExpandAll);
|
|
43863
|
+
document.getElementById("sb-collapse-all")?.removeEventListener("click", onCollapseAll);
|
|
43864
|
+
document.getElementById("filelist")?.replaceChildren();
|
|
43865
|
+
document.getElementById("diff")?.replaceChildren();
|
|
43866
|
+
document.body.classList.remove("gdp-worktree-page");
|
|
43867
|
+
mounted = false;
|
|
43868
|
+
}
|
|
43869
|
+
function selectedWorktree() {
|
|
43870
|
+
const id = route()?.wt;
|
|
43871
|
+
if (!id || !data) return null;
|
|
43872
|
+
return data.worktrees.find((item) => item.id === id) || null;
|
|
43873
|
+
}
|
|
43874
|
+
function worktreeLabel(id) {
|
|
43875
|
+
const item = data?.worktrees.find((candidate) => candidate.id === id);
|
|
43876
|
+
if (!item) return id;
|
|
43877
|
+
const sameName = data?.worktrees.filter(
|
|
43878
|
+
(candidate) => candidate.name === item.name
|
|
43879
|
+
);
|
|
43880
|
+
return sameName && sameName.length > 1 ? `${item.name} (${item.displayPath})` : item.name;
|
|
43881
|
+
}
|
|
43882
|
+
function navigate(next, replace2 = false) {
|
|
43883
|
+
const current = route();
|
|
43884
|
+
if (!current) return;
|
|
43885
|
+
deps.setRoute(
|
|
43886
|
+
{
|
|
43887
|
+
screen: "worktree",
|
|
43888
|
+
...current.wt ? { wt: current.wt } : {},
|
|
43889
|
+
...current.file ? { file: current.file } : {},
|
|
43890
|
+
...current.origin ? { origin: current.origin } : {},
|
|
43891
|
+
...next,
|
|
43892
|
+
range: deps.currentRange()
|
|
43893
|
+
},
|
|
43894
|
+
replace2
|
|
43895
|
+
);
|
|
43896
|
+
}
|
|
43897
|
+
async function refreshOnce() {
|
|
43898
|
+
if (!mounted || !route()) return;
|
|
43899
|
+
const seq = ++lifecycle;
|
|
43900
|
+
if (!data) setMessage(text3().loading);
|
|
43901
|
+
renderList();
|
|
43902
|
+
deps.setStatus("refreshing");
|
|
43903
|
+
try {
|
|
43904
|
+
const next = await deps.trackLoad(
|
|
43905
|
+
fetch("/_worktree/list").then(async (res) => {
|
|
43906
|
+
if (!res.ok) throw new Error(await res.text() || `${res.status}`);
|
|
43907
|
+
return await res.json();
|
|
43908
|
+
})
|
|
43909
|
+
);
|
|
43910
|
+
if (!isCurrent(seq)) return;
|
|
43911
|
+
if (!Number.isInteger(next.generation) || next.generation < acceptedServerGeneration) {
|
|
43912
|
+
throw new Error(
|
|
43913
|
+
`stale worktree response generation ${next.generation}; current is ${acceptedServerGeneration}`
|
|
43914
|
+
);
|
|
43915
|
+
}
|
|
43916
|
+
acceptedServerGeneration = next.generation;
|
|
43917
|
+
data = next;
|
|
43918
|
+
setMessage(next.error || "", !!next.error);
|
|
43919
|
+
deps.setStatus(next.error ? "error" : "live");
|
|
43920
|
+
} catch (error2) {
|
|
43921
|
+
if (!isCurrent(seq)) return;
|
|
43922
|
+
setMessage(
|
|
43923
|
+
error2 instanceof Error ? error2.message : text3().loadFailed,
|
|
43924
|
+
true
|
|
43925
|
+
);
|
|
43926
|
+
deps.setStatus("error");
|
|
43927
|
+
} finally {
|
|
43928
|
+
if (isCurrent(seq)) {
|
|
43929
|
+
diffFor = null;
|
|
43930
|
+
render();
|
|
43931
|
+
}
|
|
43932
|
+
}
|
|
43933
|
+
}
|
|
43934
|
+
function refresh() {
|
|
43935
|
+
if (!mounted || !route()) return Promise.resolve();
|
|
43936
|
+
refreshRequested = true;
|
|
43937
|
+
if (refreshLoop) return refreshLoop;
|
|
43938
|
+
const loop = (async () => {
|
|
43939
|
+
while (refreshRequested && mounted && route()) {
|
|
43940
|
+
refreshRequested = false;
|
|
43941
|
+
await refreshOnce();
|
|
43942
|
+
}
|
|
43943
|
+
})();
|
|
43944
|
+
const tracked = loop.finally(() => {
|
|
43945
|
+
if (refreshLoop === tracked) refreshLoop = null;
|
|
43946
|
+
});
|
|
43947
|
+
refreshLoop = tracked;
|
|
43948
|
+
return tracked;
|
|
43949
|
+
}
|
|
43950
|
+
function openBlankTab() {
|
|
43951
|
+
try {
|
|
43952
|
+
const tab = window.open("", "_blank");
|
|
43953
|
+
if (tab) tab.opener = null;
|
|
43954
|
+
return tab;
|
|
43955
|
+
} catch {
|
|
43956
|
+
return null;
|
|
43957
|
+
}
|
|
43958
|
+
}
|
|
43959
|
+
async function openWorktree(item) {
|
|
43960
|
+
if (busyPath) return;
|
|
43961
|
+
const seq = lifecycle;
|
|
43962
|
+
busyPath = item.path;
|
|
43963
|
+
setMessage(text3().opening);
|
|
43964
|
+
renderList();
|
|
43965
|
+
const tab = openBlankTab();
|
|
43966
|
+
try {
|
|
43967
|
+
const result = await deps.trackLoad(
|
|
43968
|
+
postWorktreeAction("/_worktree/open", { path: item.path })
|
|
43969
|
+
);
|
|
43970
|
+
const url = result.url || "";
|
|
43971
|
+
if (!url) throw new Error(text3().openFailed);
|
|
43972
|
+
if (tab) tab.location.href = url;
|
|
43973
|
+
if (isCurrent(seq)) setMessage(tab ? "" : url, !tab);
|
|
43974
|
+
} catch (error2) {
|
|
43975
|
+
tab?.close();
|
|
43976
|
+
if (isCurrent(seq)) {
|
|
43977
|
+
setMessage(
|
|
43978
|
+
error2 instanceof Error ? error2.message : text3().openFailed,
|
|
43979
|
+
true
|
|
43980
|
+
);
|
|
43981
|
+
}
|
|
43982
|
+
} finally {
|
|
43983
|
+
busyPath = "";
|
|
43984
|
+
if (isCurrent(seq)) await refresh();
|
|
43985
|
+
}
|
|
43986
|
+
}
|
|
43987
|
+
function labeledInput(label, placeholder, hint) {
|
|
43988
|
+
const wrap = document.createElement("label");
|
|
43989
|
+
wrap.className = "worktree-field";
|
|
43990
|
+
wrap.appendChild(el("span", "", label));
|
|
43991
|
+
const input2 = el("input", "gdp-dialog-input");
|
|
43992
|
+
input2.type = "text";
|
|
43993
|
+
input2.placeholder = placeholder;
|
|
43994
|
+
wrap.appendChild(input2);
|
|
43995
|
+
if (hint) wrap.appendChild(el("span", "worktree-hint", hint));
|
|
43996
|
+
return { wrap, input: input2 };
|
|
43997
|
+
}
|
|
43998
|
+
async function addWorktree() {
|
|
43999
|
+
const seq = lifecycle;
|
|
44000
|
+
const t2 = text3();
|
|
44001
|
+
const body = el("div", "worktree-form");
|
|
44002
|
+
body.appendChild(el("p", "worktree-hint", t2.addDialog.intro));
|
|
44003
|
+
const name = labeledInput(
|
|
44004
|
+
t2.addDialog.nameLabel,
|
|
44005
|
+
t2.addDialog.namePlaceholder
|
|
44006
|
+
);
|
|
44007
|
+
const branch = labeledInput(
|
|
44008
|
+
t2.addDialog.branchLabel,
|
|
44009
|
+
t2.addDialog.branchPlaceholder,
|
|
44010
|
+
t2.addDialog.branchHint
|
|
44011
|
+
);
|
|
44012
|
+
body.append(name.wrap, branch.wrap);
|
|
44013
|
+
const parent = data?.addParent || "";
|
|
44014
|
+
if (parent) {
|
|
44015
|
+
const targetRow = el("div", "worktree-target");
|
|
44016
|
+
targetRow.appendChild(
|
|
44017
|
+
el("span", "worktree-target-label", t2.addDialog.targetLabel)
|
|
44018
|
+
);
|
|
44019
|
+
const targetPath = el("span", "worktree-target-path");
|
|
44020
|
+
targetRow.appendChild(targetPath);
|
|
44021
|
+
const hint = el("span", "worktree-hint-mark", "?");
|
|
44022
|
+
hint.title = t2.gitignoreHint;
|
|
44023
|
+
hint.tabIndex = 0;
|
|
44024
|
+
hint.setAttribute("role", "note");
|
|
44025
|
+
hint.setAttribute(
|
|
44026
|
+
"aria-label",
|
|
44027
|
+
`${t2.addDialog.gitignoreLabel}: ${t2.gitignoreHint}`
|
|
44028
|
+
);
|
|
44029
|
+
targetRow.appendChild(hint);
|
|
44030
|
+
body.appendChild(targetRow);
|
|
44031
|
+
const syncTarget = () => {
|
|
44032
|
+
const value = name.input.value.trim();
|
|
44033
|
+
targetPath.textContent = value ? `${parent}/${value}` : t2.addDialog.targetPending(parent);
|
|
44034
|
+
targetPath.title = targetPath.textContent;
|
|
44035
|
+
};
|
|
44036
|
+
name.input.addEventListener("input", syncTarget);
|
|
44037
|
+
syncTarget();
|
|
44038
|
+
}
|
|
44039
|
+
const submitted = await showFormDialog({
|
|
44040
|
+
title: t2.addDialog.title,
|
|
44041
|
+
body,
|
|
44042
|
+
submitLabel: t2.addDialog.submit,
|
|
44043
|
+
cancelLabel: t2.cancel,
|
|
44044
|
+
focusTarget: name.input,
|
|
44045
|
+
validate: () => {
|
|
44046
|
+
const nameError = worktreeNameError(name.input.value.trim());
|
|
44047
|
+
if (nameError) return t2.nameErrors[nameError];
|
|
44048
|
+
const raw = branch.input.value.trim();
|
|
44049
|
+
if (!raw) return null;
|
|
44050
|
+
const branchError = worktreeBranchError(raw);
|
|
44051
|
+
return branchError ? t2.nameErrors[branchError] : null;
|
|
44052
|
+
},
|
|
44053
|
+
submit: () => ({
|
|
44054
|
+
name: name.input.value.trim(),
|
|
44055
|
+
branch: branch.input.value.trim()
|
|
44056
|
+
})
|
|
44057
|
+
});
|
|
44058
|
+
if (!submitted) return;
|
|
44059
|
+
if (!isCurrent(seq)) return;
|
|
44060
|
+
let createdPath = "";
|
|
44061
|
+
try {
|
|
44062
|
+
const result = await deps.trackLoad(
|
|
44063
|
+
postWorktreeAction("/_worktree/add", submitted)
|
|
44064
|
+
);
|
|
44065
|
+
if (isCurrent(seq)) setMessage("");
|
|
44066
|
+
createdPath = result.path || "";
|
|
44067
|
+
} catch (error2) {
|
|
44068
|
+
if (isCurrent(seq)) {
|
|
44069
|
+
setMessage(error2 instanceof Error ? error2.message : t2.addFailed, true);
|
|
44070
|
+
}
|
|
44071
|
+
}
|
|
44072
|
+
if (isCurrent(seq) && createdPath) {
|
|
44073
|
+
navigate({ wt: createdPath });
|
|
44074
|
+
}
|
|
44075
|
+
if (isCurrent(seq)) await refresh();
|
|
44076
|
+
}
|
|
44077
|
+
async function removeWorktree(item) {
|
|
44078
|
+
if (busyPath) return;
|
|
44079
|
+
const seq = lifecycle;
|
|
44080
|
+
const t2 = text3();
|
|
44081
|
+
const body = el("div", "worktree-form");
|
|
44082
|
+
if (item.missing) {
|
|
44083
|
+
body.appendChild(el("p", "", t2.removeDialog.missingBody(item.name)));
|
|
44084
|
+
body.appendChild(el("p", "worktree-hint", t2.removeDialog.missingNote));
|
|
44085
|
+
if (item.locked) {
|
|
44086
|
+
body.appendChild(el("p", "worktree-warn", t2.removeDialog.lockedNote));
|
|
44087
|
+
}
|
|
44088
|
+
const otherMissing = (data?.worktrees || []).filter(
|
|
44089
|
+
(candidate) => candidate.missing && !candidate.locked && candidate.id !== item.id
|
|
44090
|
+
).length;
|
|
44091
|
+
if (otherMissing > 0) {
|
|
44092
|
+
body.appendChild(
|
|
44093
|
+
el("p", "worktree-hint", t2.removeDialog.missingOthers(otherMissing))
|
|
44094
|
+
);
|
|
44095
|
+
}
|
|
44096
|
+
} else {
|
|
44097
|
+
body.appendChild(el("p", "", t2.removeDialog.body(item.name)));
|
|
44098
|
+
body.appendChild(el("p", "", t2.removeDialog.diskNote(item.path)));
|
|
44099
|
+
}
|
|
44100
|
+
if (item.branch) {
|
|
44101
|
+
body.appendChild(
|
|
44102
|
+
el("p", "worktree-hint", t2.removeDialog.branchNote(item.branch))
|
|
44103
|
+
);
|
|
44104
|
+
}
|
|
44105
|
+
let force = null;
|
|
44106
|
+
if (!item.missing && item.changedCount > 0) {
|
|
44107
|
+
const warn = el("p", "worktree-warn");
|
|
44108
|
+
warn.appendChild(
|
|
44109
|
+
el("span", "", `⚠ ${t2.removeDialog.dirtyNote(item.changedCount)}`)
|
|
44110
|
+
);
|
|
44111
|
+
warn.appendChild(document.createElement("br"));
|
|
44112
|
+
warn.appendChild(el("span", "", t2.removeDialog.dirtyLose));
|
|
44113
|
+
body.appendChild(warn);
|
|
44114
|
+
const forceWrap = document.createElement("label");
|
|
44115
|
+
forceWrap.className = "worktree-check";
|
|
44116
|
+
force = document.createElement("input");
|
|
44117
|
+
force.type = "checkbox";
|
|
44118
|
+
forceWrap.append(force, el("span", "", t2.removeDialog.force));
|
|
44119
|
+
body.appendChild(forceWrap);
|
|
44120
|
+
}
|
|
44121
|
+
const submitted = await showFormDialog({
|
|
44122
|
+
title: t2.removeDialog.title,
|
|
44123
|
+
body,
|
|
44124
|
+
submitLabel: t2.removeDialog.submit,
|
|
44125
|
+
cancelLabel: t2.cancel,
|
|
44126
|
+
// フォルダごと消える不可逆の操作なので、確定は常に危険色。
|
|
44127
|
+
danger: true,
|
|
44128
|
+
validate: () => force && !force.checked ? t2.removeDialog.forceRequired : null,
|
|
44129
|
+
submit: () => ({ force: force?.checked ?? false })
|
|
44130
|
+
});
|
|
44131
|
+
if (!submitted) return;
|
|
44132
|
+
if (!isCurrent(seq)) return;
|
|
44133
|
+
busyPath = item.path;
|
|
44134
|
+
renderList();
|
|
44135
|
+
try {
|
|
44136
|
+
await deps.trackLoad(
|
|
44137
|
+
postWorktreeAction("/_worktree/remove", {
|
|
44138
|
+
path: item.path,
|
|
44139
|
+
force: submitted.force
|
|
44140
|
+
})
|
|
44141
|
+
);
|
|
44142
|
+
if (isCurrent(seq)) setMessage("");
|
|
44143
|
+
if (isCurrent(seq) && route()?.wt === item.id) {
|
|
44144
|
+
navigate({ wt: void 0, file: void 0, origin: void 0 }, true);
|
|
44145
|
+
}
|
|
44146
|
+
} catch (error2) {
|
|
44147
|
+
if (isCurrent(seq)) {
|
|
44148
|
+
setMessage(
|
|
44149
|
+
error2 instanceof Error ? error2.message : t2.removeFailed,
|
|
44150
|
+
true
|
|
44151
|
+
);
|
|
44152
|
+
}
|
|
44153
|
+
} finally {
|
|
44154
|
+
busyPath = "";
|
|
44155
|
+
if (isCurrent(seq)) await refresh();
|
|
44156
|
+
}
|
|
44157
|
+
}
|
|
44158
|
+
function overlapOthers(item, file) {
|
|
44159
|
+
const paths = new Set([file.path, file.oldPath].filter(Boolean));
|
|
44160
|
+
const ownerIds = new Set(
|
|
44161
|
+
(data?.overlaps || []).filter((overlap) => paths.has(overlap.path)).flatMap((overlap) => overlap.worktreeIds)
|
|
44162
|
+
);
|
|
44163
|
+
return [...ownerIds].filter((id) => id !== item.id).map((id) => worktreeLabel(id));
|
|
44164
|
+
}
|
|
44165
|
+
function divergenceSummary(item) {
|
|
44166
|
+
const t2 = text3();
|
|
44167
|
+
const divergence = item.divergence;
|
|
44168
|
+
if (!divergence) return t2.diverge.notComparable;
|
|
44169
|
+
const parts = [];
|
|
44170
|
+
if (divergence.mergeState === "clean") {
|
|
44171
|
+
parts.push(t2.merge.clean);
|
|
44172
|
+
} else if (divergence.mergeState === "conflict") {
|
|
44173
|
+
parts.push(t2.merge.conflict(divergence.conflicts.length));
|
|
44174
|
+
} else {
|
|
44175
|
+
parts.push(t2.merge.unknown);
|
|
44176
|
+
}
|
|
44177
|
+
if (divergence.ahead > 0) {
|
|
44178
|
+
parts.push(t2.diverge.ahead(divergence.ahead, divergence.base));
|
|
44179
|
+
}
|
|
44180
|
+
if (divergence.behind > 0) {
|
|
44181
|
+
parts.push(t2.diverge.behind(divergence.behind, divergence.base));
|
|
44182
|
+
}
|
|
44183
|
+
if (!divergence.ahead && !divergence.behind) {
|
|
44184
|
+
parts.push(t2.diverge.even(divergence.base));
|
|
44185
|
+
}
|
|
44186
|
+
return parts.join(" · ");
|
|
44187
|
+
}
|
|
44188
|
+
function worktreeBadges(item) {
|
|
44189
|
+
const t2 = text3();
|
|
44190
|
+
const badges = [];
|
|
44191
|
+
if (item.current) {
|
|
44192
|
+
badges.push({ label: t2.badges.current, title: t2.badges.currentTitle });
|
|
44193
|
+
}
|
|
44194
|
+
if (item.serverUrl) {
|
|
44195
|
+
badges.push({ label: t2.badges.running, title: t2.badges.runningTitle });
|
|
44196
|
+
}
|
|
44197
|
+
if (item.missing) badges.push({ label: t2.badges.missing, title: "" });
|
|
44198
|
+
if (item.bare) {
|
|
44199
|
+
badges.push({ label: t2.badges.bare, title: t2.badges.bareTitle });
|
|
44200
|
+
}
|
|
44201
|
+
if (item.locked) {
|
|
44202
|
+
badges.push({ label: t2.badges.locked, title: item.lockedReason });
|
|
44203
|
+
}
|
|
44204
|
+
if (item.prunable) {
|
|
44205
|
+
badges.push({ label: t2.badges.prunable, title: t2.badges.prunableTitle });
|
|
44206
|
+
}
|
|
44207
|
+
return badges;
|
|
44208
|
+
}
|
|
44209
|
+
function headButton(label, title, onClick) {
|
|
44210
|
+
const button = el("button", "gdp-btn gdp-btn-sm worktree-head-btn", label);
|
|
44211
|
+
button.type = "button";
|
|
44212
|
+
button.title = title;
|
|
44213
|
+
button.addEventListener("click", onClick);
|
|
44214
|
+
return button;
|
|
44215
|
+
}
|
|
44216
|
+
function openFolderButton(item, withLabel) {
|
|
44217
|
+
const arg = openPathArg(item);
|
|
44218
|
+
if (arg === null) return null;
|
|
44219
|
+
const t2 = text3();
|
|
44220
|
+
const button = deps.createOpenPathButton(
|
|
44221
|
+
arg,
|
|
44222
|
+
"directory",
|
|
44223
|
+
t2.actions.openFolderTitle
|
|
44224
|
+
);
|
|
44225
|
+
if (withLabel) {
|
|
44226
|
+
button.className = "gdp-btn gdp-btn-sm gdp-open-path";
|
|
44227
|
+
button.textContent = t2.actions.openFolder;
|
|
44228
|
+
}
|
|
44229
|
+
return button;
|
|
44230
|
+
}
|
|
44231
|
+
function copyButton(value, title, label) {
|
|
44232
|
+
const button = el(
|
|
44233
|
+
"button",
|
|
44234
|
+
label ? "gdp-btn gdp-btn-sm gdp-copy-path" : "gdp-file-header-icon gdp-copy-path",
|
|
44235
|
+
label
|
|
44236
|
+
);
|
|
44237
|
+
button.type = "button";
|
|
44238
|
+
button.title = title;
|
|
44239
|
+
button.setAttribute("aria-label", title);
|
|
44240
|
+
if (!label) button.innerHTML = iconSvg("octicon-copy", COPY_16_PATHS);
|
|
44241
|
+
button.addEventListener("click", async (event) => {
|
|
44242
|
+
event.stopPropagation();
|
|
44243
|
+
button.classList.remove("copied", "failed");
|
|
44244
|
+
button.classList.add(await copyText(value) ? "copied" : "failed");
|
|
44245
|
+
window.setTimeout(
|
|
44246
|
+
() => button.classList.remove("copied", "failed"),
|
|
44247
|
+
1200
|
|
44248
|
+
);
|
|
44249
|
+
});
|
|
44250
|
+
return button;
|
|
44251
|
+
}
|
|
44252
|
+
async function runAction(run, failure) {
|
|
44253
|
+
const seq = lifecycle;
|
|
44254
|
+
if (await run()) return;
|
|
44255
|
+
if (!isCurrent(seq)) return;
|
|
44256
|
+
setMessage(failure, true);
|
|
44257
|
+
renderList();
|
|
44258
|
+
}
|
|
44259
|
+
async function copyText(value) {
|
|
44260
|
+
try {
|
|
44261
|
+
await navigator.clipboard.writeText(value);
|
|
44262
|
+
return true;
|
|
44263
|
+
} catch (error2) {
|
|
44264
|
+
console.error("[code-viewer] failed to copy to clipboard", error2);
|
|
44265
|
+
return false;
|
|
44266
|
+
}
|
|
44267
|
+
}
|
|
44268
|
+
function copyPathButton(item, withLabel) {
|
|
44269
|
+
const t2 = text3();
|
|
44270
|
+
return copyButton(
|
|
44271
|
+
item.path,
|
|
44272
|
+
t2.actions.copyPathTitle,
|
|
44273
|
+
withLabel ? t2.actions.copyPath : void 0
|
|
44274
|
+
);
|
|
44275
|
+
}
|
|
44276
|
+
function mergeCommand(item) {
|
|
44277
|
+
const divergence = item.divergence;
|
|
44278
|
+
if (!divergence || divergence.mergeState !== "clean") return null;
|
|
44279
|
+
if (!item.branch || !divergence.base) return null;
|
|
44280
|
+
return {
|
|
44281
|
+
base: divergence.base,
|
|
44282
|
+
branch: item.branch,
|
|
44283
|
+
command: `git switch ${divergence.base} && git merge ${item.branch}`
|
|
44284
|
+
};
|
|
44285
|
+
}
|
|
44286
|
+
function copyMergeButton(item) {
|
|
44287
|
+
const merge = mergeCommand(item);
|
|
44288
|
+
if (!merge) return null;
|
|
44289
|
+
const t2 = text3();
|
|
44290
|
+
return copyButton(
|
|
44291
|
+
merge.command,
|
|
44292
|
+
t2.actions.copyMergeTitle(merge.base, merge.branch)
|
|
44293
|
+
);
|
|
44294
|
+
}
|
|
44295
|
+
async function stopWorktreeServer(item) {
|
|
44296
|
+
if (busyPath) return;
|
|
44297
|
+
const seq = lifecycle;
|
|
44298
|
+
busyPath = item.path;
|
|
44299
|
+
renderList();
|
|
44300
|
+
try {
|
|
44301
|
+
await deps.trackLoad(
|
|
44302
|
+
postWorktreeAction("/_worktree/stop", { path: item.path })
|
|
44303
|
+
);
|
|
44304
|
+
if (isCurrent(seq)) setMessage("");
|
|
44305
|
+
} catch (error2) {
|
|
44306
|
+
if (isCurrent(seq)) {
|
|
44307
|
+
setMessage(
|
|
44308
|
+
error2 instanceof Error ? error2.message : text3().actions.stopFailed,
|
|
44309
|
+
true
|
|
44310
|
+
);
|
|
44311
|
+
}
|
|
44312
|
+
} finally {
|
|
44313
|
+
busyPath = "";
|
|
44314
|
+
if (isCurrent(seq)) await refresh();
|
|
44315
|
+
}
|
|
44316
|
+
}
|
|
44317
|
+
function openPathArg(item) {
|
|
44318
|
+
const shown = item.displayPath;
|
|
44319
|
+
if (shown === ".") return "";
|
|
44320
|
+
if (!shown || shown.startsWith("/") || shown.startsWith("\\")) return null;
|
|
44321
|
+
return shown;
|
|
44322
|
+
}
|
|
44323
|
+
function rowMenuItems(item) {
|
|
44324
|
+
const t2 = text3();
|
|
44325
|
+
const items = [];
|
|
44326
|
+
if (!item.missing && !item.bare) {
|
|
44327
|
+
const openArg = openPathArg(item);
|
|
44328
|
+
if (openArg !== null) {
|
|
44329
|
+
items.push({
|
|
44330
|
+
label: t2.actions.openFolder,
|
|
44331
|
+
title: t2.actions.openFolderTitle,
|
|
44332
|
+
onSelect: () => {
|
|
44333
|
+
void runAction(
|
|
44334
|
+
() => deps.openPathInOs(openArg, "directory"),
|
|
44335
|
+
t2.actions.openFolderFailed
|
|
44336
|
+
);
|
|
44337
|
+
}
|
|
44338
|
+
});
|
|
44339
|
+
}
|
|
44340
|
+
items.push({
|
|
44341
|
+
label: t2.actions.copyPath,
|
|
44342
|
+
title: t2.actions.copyPathTitle,
|
|
44343
|
+
onSelect: () => {
|
|
44344
|
+
void runAction(() => copyText(item.path), t2.actions.copyFailed);
|
|
44345
|
+
}
|
|
44346
|
+
});
|
|
44347
|
+
items.push({
|
|
44348
|
+
label: t2.open,
|
|
44349
|
+
title: t2.openTitle,
|
|
44350
|
+
disabled: !!busyPath,
|
|
44351
|
+
onSelect: () => {
|
|
44352
|
+
void openWorktree(item);
|
|
44353
|
+
}
|
|
44354
|
+
});
|
|
44355
|
+
}
|
|
44356
|
+
if (item.serverUrl) {
|
|
44357
|
+
items.push({
|
|
44358
|
+
label: t2.actions.copyServerUrl,
|
|
44359
|
+
title: t2.actions.copyServerUrlTitle(item.serverUrl),
|
|
44360
|
+
onSelect: () => {
|
|
44361
|
+
void runAction(() => copyText(item.serverUrl), t2.actions.copyFailed);
|
|
44362
|
+
}
|
|
44363
|
+
});
|
|
44364
|
+
}
|
|
44365
|
+
if (item.serverUrl && !item.current) {
|
|
44366
|
+
items.push({
|
|
44367
|
+
label: t2.actions.stopServer,
|
|
44368
|
+
title: t2.actions.stopServerTitle,
|
|
44369
|
+
disabled: !!busyPath,
|
|
44370
|
+
onSelect: () => {
|
|
44371
|
+
void stopWorktreeServer(item);
|
|
44372
|
+
}
|
|
44373
|
+
});
|
|
44374
|
+
}
|
|
44375
|
+
const merge = mergeCommand(item);
|
|
44376
|
+
if (merge) {
|
|
44377
|
+
items.push({
|
|
44378
|
+
label: t2.actions.copyMerge,
|
|
44379
|
+
title: t2.actions.copyMergeTitle(merge.base, merge.branch),
|
|
44380
|
+
onSelect: () => {
|
|
44381
|
+
void runAction(() => copyText(merge.command), t2.actions.copyFailed);
|
|
44382
|
+
}
|
|
44383
|
+
});
|
|
44384
|
+
}
|
|
44385
|
+
if (!item.current) {
|
|
44386
|
+
if (items.length) items.push({ kind: "separator" });
|
|
44387
|
+
items.push({
|
|
44388
|
+
label: t2.remove,
|
|
44389
|
+
title: t2.removeTitle,
|
|
44390
|
+
danger: true,
|
|
44391
|
+
disabled: !!busyPath,
|
|
44392
|
+
onSelect: () => {
|
|
44393
|
+
void removeWorktree(item);
|
|
44394
|
+
}
|
|
44395
|
+
});
|
|
44396
|
+
}
|
|
44397
|
+
return items;
|
|
44398
|
+
}
|
|
44399
|
+
function rowMenuButton(item) {
|
|
44400
|
+
const items = rowMenuItems(item);
|
|
44401
|
+
if (!items.length) return null;
|
|
44402
|
+
const t2 = text3();
|
|
44403
|
+
const button = el("button", "worktree-row-menu");
|
|
44404
|
+
button.type = "button";
|
|
44405
|
+
button.title = t2.actions.menuTitle;
|
|
44406
|
+
button.setAttribute("aria-label", t2.actions.menuFor(item.name));
|
|
44407
|
+
button.setAttribute("aria-haspopup", "menu");
|
|
44408
|
+
button.innerHTML = iconSvg("octicon-kebab-horizontal", KEBAB_16_PATH);
|
|
44409
|
+
button.addEventListener("click", (event) => {
|
|
44410
|
+
event.stopPropagation();
|
|
44411
|
+
showContextMenu(button, rowMenuItems(item));
|
|
44412
|
+
});
|
|
44413
|
+
return button;
|
|
44414
|
+
}
|
|
44415
|
+
function note(body, isError = false) {
|
|
44416
|
+
const node = el("div", "history-status", body);
|
|
44417
|
+
node.hidden = false;
|
|
44418
|
+
if (isError) {
|
|
44419
|
+
node.setAttribute("role", "alert");
|
|
44420
|
+
node.style.color = "var(--danger)";
|
|
44421
|
+
}
|
|
44422
|
+
return node;
|
|
44423
|
+
}
|
|
44424
|
+
function renderList() {
|
|
44425
|
+
if (!listPanel) return;
|
|
44426
|
+
const t2 = text3();
|
|
44427
|
+
listPanel.replaceChildren();
|
|
44428
|
+
const head = el("div", "history-head");
|
|
44429
|
+
head.appendChild(el("span", "history-title", t2.panes.worktrees));
|
|
44430
|
+
head.appendChild(
|
|
44431
|
+
headButton(t2.refresh, t2.refreshTitle, () => {
|
|
44432
|
+
void refresh();
|
|
44433
|
+
})
|
|
44434
|
+
);
|
|
44435
|
+
head.appendChild(
|
|
44436
|
+
headButton(t2.add, t2.addTitle, () => {
|
|
44437
|
+
void addWorktree();
|
|
44438
|
+
})
|
|
44439
|
+
);
|
|
44440
|
+
listPanel.appendChild(head);
|
|
44441
|
+
worktreeFilterInput.placeholder = t2.panes.filterWorktrees;
|
|
44442
|
+
const filterWrap = el("div", "history-filter-wrap");
|
|
44443
|
+
filterWrap.appendChild(worktreeFilterInput);
|
|
44444
|
+
listPanel.appendChild(filterWrap);
|
|
44445
|
+
if (data && !data.baseBranch) {
|
|
44446
|
+
listPanel.appendChild(note(t2.baseUnknown));
|
|
44447
|
+
}
|
|
44448
|
+
if (message) listPanel.appendChild(note(message, messageIsError));
|
|
44449
|
+
const overlaps = data?.overlaps || [];
|
|
44450
|
+
if (overlaps.length) {
|
|
44451
|
+
const banner = el("div", "history-banner");
|
|
44452
|
+
banner.hidden = false;
|
|
44453
|
+
banner.textContent = `${t2.overlaps.heading(overlaps.length)} — ${t2.overlaps.intro}`;
|
|
44454
|
+
banner.title = overlaps.map(
|
|
44455
|
+
(overlap) => t2.overlaps.entry(
|
|
44456
|
+
overlap.path,
|
|
44457
|
+
overlap.worktreeIds.map((id) => worktreeLabel(id))
|
|
44458
|
+
)
|
|
44459
|
+
).join("\n");
|
|
44460
|
+
listPanel.appendChild(banner);
|
|
44461
|
+
}
|
|
44462
|
+
if (!data) {
|
|
44463
|
+
listPanel.appendChild(note(t2.loading));
|
|
44464
|
+
return;
|
|
44465
|
+
}
|
|
44466
|
+
if (!data.worktrees.length) {
|
|
44467
|
+
listPanel.appendChild(note(t2.empty));
|
|
44468
|
+
return;
|
|
44469
|
+
}
|
|
44470
|
+
const items = data.worktrees.filter(
|
|
44471
|
+
(item) => matches(item.name, worktreeFilter) || matches(item.branch, worktreeFilter) || matches(item.displayPath, worktreeFilter)
|
|
44472
|
+
);
|
|
44473
|
+
if (!items.length) {
|
|
44474
|
+
listPanel.appendChild(note(t2.panes.noWorktreeMatch));
|
|
44475
|
+
return;
|
|
44476
|
+
}
|
|
44477
|
+
const list2 = el("ol", "history-list");
|
|
44478
|
+
const selected = route()?.wt;
|
|
44479
|
+
for (const item of items) {
|
|
44480
|
+
const row = el("li", "history-item");
|
|
44481
|
+
row.dataset.wt = item.id;
|
|
44482
|
+
if (item.id === selected) row.classList.add("active");
|
|
44483
|
+
if (item.divergence?.mergeState === "conflict") {
|
|
44484
|
+
row.classList.add("worktree-conflict");
|
|
44485
|
+
}
|
|
44486
|
+
const head2 = el("span", "worktree-row-head");
|
|
44487
|
+
const subject = el("span", "subject", item.name);
|
|
44488
|
+
subject.title = item.path;
|
|
44489
|
+
head2.appendChild(subject);
|
|
44490
|
+
const badges = worktreeBadges(item);
|
|
44491
|
+
if (badges.length) {
|
|
44492
|
+
const wrap = el("span", "worktree-row-badges");
|
|
44493
|
+
badges.forEach((badge, index) => {
|
|
44494
|
+
if (index) wrap.appendChild(document.createTextNode(" · "));
|
|
44495
|
+
const node = el("span", "worktree-badge", badge.label);
|
|
44496
|
+
node.title = badge.title;
|
|
44497
|
+
wrap.appendChild(node);
|
|
44498
|
+
});
|
|
44499
|
+
head2.appendChild(wrap);
|
|
44500
|
+
}
|
|
44501
|
+
const menu = rowMenuButton(item);
|
|
44502
|
+
if (menu) head2.appendChild(menu);
|
|
44503
|
+
row.appendChild(head2);
|
|
44504
|
+
const pathLine = el("span", "worktree-row-path", item.path);
|
|
44505
|
+
pathLine.title = item.path;
|
|
44506
|
+
row.appendChild(pathLine);
|
|
44507
|
+
const meta = el("span", "meta2");
|
|
44508
|
+
const branchName = el("span", "sha", item.branch || t2.badges.detached);
|
|
44509
|
+
if (!item.branch) branchName.title = t2.badges.detachedTitle;
|
|
44510
|
+
meta.appendChild(branchName);
|
|
44511
|
+
meta.appendChild(
|
|
44512
|
+
el(
|
|
44513
|
+
"span",
|
|
44514
|
+
"author",
|
|
44515
|
+
item.fileCount ? t2.files.heading(item.fileCount) : t2.files.none
|
|
44516
|
+
)
|
|
44517
|
+
);
|
|
44518
|
+
if (item.lastCommit) {
|
|
44519
|
+
const parsed = Date.parse(item.lastCommit.when);
|
|
44520
|
+
const when = el(
|
|
44521
|
+
"span",
|
|
44522
|
+
"when",
|
|
44523
|
+
Number.isFinite(parsed) ? blameRelativeTime(Math.round(parsed / 1e3)) : item.lastCommit.when
|
|
44524
|
+
);
|
|
44525
|
+
when.title = Number.isFinite(parsed) ? `${item.lastCommit.subject}
|
|
44526
|
+
${new Date(parsed).toLocaleString()}` : item.lastCommit.subject;
|
|
44527
|
+
meta.appendChild(when);
|
|
44528
|
+
}
|
|
44529
|
+
if (item.lastTouched) {
|
|
44530
|
+
const parsed = Date.parse(item.lastTouched);
|
|
44531
|
+
const when = el(
|
|
44532
|
+
"span",
|
|
44533
|
+
"when",
|
|
44534
|
+
Number.isFinite(parsed) ? t2.lastTouched(blameRelativeTime(Math.round(parsed / 1e3))) : t2.lastTouched(item.lastTouched)
|
|
44535
|
+
);
|
|
44536
|
+
when.title = Number.isFinite(parsed) ? new Date(parsed).toLocaleString() : item.lastTouched;
|
|
44537
|
+
meta.appendChild(when);
|
|
44538
|
+
}
|
|
44539
|
+
row.appendChild(meta);
|
|
44540
|
+
const second = el("span", "meta2");
|
|
44541
|
+
const summary = divergenceSummary(item);
|
|
44542
|
+
const summaryText = el("span", "author", summary);
|
|
44543
|
+
summaryText.title = summary;
|
|
44544
|
+
second.appendChild(summaryText);
|
|
44545
|
+
const merge = copyMergeButton(item);
|
|
44546
|
+
if (merge) second.appendChild(merge);
|
|
44547
|
+
row.appendChild(second);
|
|
44548
|
+
if (item.error) {
|
|
44549
|
+
const error2 = el("span", "meta2");
|
|
44550
|
+
const detail = el("span", "author", item.error);
|
|
44551
|
+
detail.style.color = "var(--danger)";
|
|
44552
|
+
error2.appendChild(detail);
|
|
44553
|
+
row.appendChild(error2);
|
|
44554
|
+
}
|
|
44555
|
+
list2.appendChild(row);
|
|
44556
|
+
}
|
|
44557
|
+
list2.addEventListener("click", (event) => {
|
|
44558
|
+
const row = event.target?.closest(
|
|
44559
|
+
".history-item"
|
|
44560
|
+
);
|
|
44561
|
+
const id = row?.dataset.wt;
|
|
44562
|
+
if (!id) return;
|
|
44563
|
+
navigate({ wt: id, file: void 0, origin: void 0 });
|
|
44564
|
+
});
|
|
44565
|
+
listPanel.appendChild(list2);
|
|
44566
|
+
if (data.worktrees.length === 1) {
|
|
44567
|
+
listPanel.appendChild(note(t2.intro.listNote));
|
|
44568
|
+
}
|
|
44569
|
+
}
|
|
44570
|
+
function introCard() {
|
|
44571
|
+
const t2 = text3();
|
|
44572
|
+
const card = el("div", "worktree-intro");
|
|
44573
|
+
card.appendChild(el("p", "worktree-intro-title", t2.intro.cardTitle));
|
|
44574
|
+
card.appendChild(el("p", "", t2.intro.cardWhat));
|
|
44575
|
+
card.appendChild(el("p", "", t2.intro.cardWhy));
|
|
44576
|
+
card.appendChild(el("p", "", t2.intro.cardHow));
|
|
44577
|
+
const button = el("button", "gdp-btn gdp-btn-sm", t2.intro.cardButton);
|
|
44578
|
+
button.type = "button";
|
|
44579
|
+
button.addEventListener("click", () => {
|
|
44580
|
+
void addWorktree();
|
|
44581
|
+
});
|
|
44582
|
+
card.appendChild(button);
|
|
44583
|
+
return card;
|
|
44584
|
+
}
|
|
44585
|
+
function visibleFiles(item) {
|
|
44586
|
+
const hideTests = deps.getOptions().hideTests;
|
|
44587
|
+
return item.files.filter(
|
|
44588
|
+
(file) => matches(file.path, fileFilter) && !(hideTests && deps.isTestPath(file.path))
|
|
44589
|
+
);
|
|
44590
|
+
}
|
|
44591
|
+
function emptyTree() {
|
|
44592
|
+
return { dirs: /* @__PURE__ */ new Map(), files: [] };
|
|
44593
|
+
}
|
|
44594
|
+
function buildTree(files) {
|
|
44595
|
+
const root = emptyTree();
|
|
44596
|
+
for (const file of files) {
|
|
44597
|
+
const parts = file.path.split("/");
|
|
44598
|
+
let node = root;
|
|
44599
|
+
for (let i2 = 0; i2 < parts.length - 1; i2++) {
|
|
44600
|
+
const name = parts[i2];
|
|
44601
|
+
let child = node.dirs.get(name);
|
|
44602
|
+
if (!child) {
|
|
44603
|
+
child = emptyTree();
|
|
44604
|
+
node.dirs.set(name, child);
|
|
44605
|
+
}
|
|
44606
|
+
node = child;
|
|
44607
|
+
}
|
|
44608
|
+
node.files.push(file);
|
|
44609
|
+
}
|
|
44610
|
+
return root;
|
|
44611
|
+
}
|
|
44612
|
+
function collapseChain(name, node) {
|
|
44613
|
+
let label = name;
|
|
44614
|
+
let current = node;
|
|
44615
|
+
while (current.files.length === 0 && current.dirs.size === 1) {
|
|
44616
|
+
const [childName, child] = [...current.dirs.entries()][0];
|
|
44617
|
+
label = `${label}/${childName}`;
|
|
44618
|
+
current = child;
|
|
44619
|
+
}
|
|
44620
|
+
return [label, current];
|
|
44621
|
+
}
|
|
44622
|
+
function fileRow(item, file, depth, label) {
|
|
44623
|
+
const t2 = text3();
|
|
44624
|
+
const row = el("li", "tree-file");
|
|
44625
|
+
row.tabIndex = -1;
|
|
44626
|
+
row.dataset.path = file.path;
|
|
44627
|
+
row.dataset.key = fileKey(file);
|
|
44628
|
+
row.dataset.type = "blob";
|
|
44629
|
+
const currentRoute = route();
|
|
44630
|
+
if (currentRoute?.file === file.path && currentRoute.origin === file.origin) {
|
|
44631
|
+
row.classList.add("active");
|
|
44632
|
+
}
|
|
44633
|
+
row.style.setProperty("--lvl-pad", `${12 + depth * 14}px`);
|
|
44634
|
+
row.appendChild(el("span", "chev-spacer"));
|
|
44635
|
+
const badge = el("span", `badge ${file.status}`, file.status);
|
|
44636
|
+
badge.title = t2.files.statusTitles[file.status] || file.status;
|
|
44637
|
+
row.appendChild(badge);
|
|
44638
|
+
const name = el("span", "name", label);
|
|
44639
|
+
name.title = file.path;
|
|
44640
|
+
row.appendChild(name);
|
|
44641
|
+
const others = overlapOthers(item, file);
|
|
44642
|
+
if (others.length) {
|
|
44643
|
+
row.classList.add("worktree-overlap");
|
|
44644
|
+
const mark = el(
|
|
44645
|
+
"span",
|
|
44646
|
+
"stat worktree-overlap-count",
|
|
44647
|
+
String(others.length)
|
|
44648
|
+
);
|
|
44649
|
+
mark.title = t2.files.overlapTitle(others);
|
|
44650
|
+
row.appendChild(mark);
|
|
44651
|
+
name.title = `${file.path}
|
|
44652
|
+
${t2.files.overlapTitle(others)}`;
|
|
44653
|
+
}
|
|
44654
|
+
return row;
|
|
44655
|
+
}
|
|
44656
|
+
function renderTreeInto(parent, item, node, depth) {
|
|
44657
|
+
for (const [rawName, rawChild] of node.dirs) {
|
|
44658
|
+
const [label, child] = collapseChain(rawName, rawChild);
|
|
44659
|
+
const li = el("li", "tree-dir");
|
|
44660
|
+
li.tabIndex = -1;
|
|
44661
|
+
li.dataset.type = "tree";
|
|
44662
|
+
li.style.setProperty("--lvl-pad", `${12 + depth * 14}px`);
|
|
44663
|
+
const chev = el("span", "chev");
|
|
44664
|
+
chev.innerHTML = chevronSvg();
|
|
44665
|
+
const icon = el("span", "dir-icon");
|
|
44666
|
+
icon.innerHTML = folderSvg(false);
|
|
44667
|
+
const name = el("span", "name", label);
|
|
44668
|
+
name.title = label;
|
|
44669
|
+
li.append(chev, icon, name);
|
|
44670
|
+
const toggle = (event) => {
|
|
44671
|
+
event.stopPropagation();
|
|
44672
|
+
const collapsed = li.classList.toggle("collapsed");
|
|
44673
|
+
icon.innerHTML = folderSvg(collapsed);
|
|
44674
|
+
};
|
|
44675
|
+
chev.addEventListener("click", toggle);
|
|
44676
|
+
icon.addEventListener("click", toggle);
|
|
44677
|
+
parent.appendChild(li);
|
|
44678
|
+
const children = el("ul", "tree-children");
|
|
44679
|
+
renderTreeInto(children, item, child, depth + 1);
|
|
44680
|
+
parent.appendChild(children);
|
|
44681
|
+
}
|
|
44682
|
+
for (const file of node.files) {
|
|
44683
|
+
const parts = file.path.split("/");
|
|
44684
|
+
parent.appendChild(
|
|
44685
|
+
fileRow(item, file, depth, parts[parts.length - 1] || file.path)
|
|
44686
|
+
);
|
|
44687
|
+
}
|
|
44688
|
+
}
|
|
44689
|
+
function renderFiles() {
|
|
44690
|
+
const t2 = text3();
|
|
44691
|
+
const list2 = document.getElementById("filelist");
|
|
44692
|
+
const title = document.querySelector(".sb-title");
|
|
44693
|
+
const totals = document.getElementById("totals");
|
|
44694
|
+
if (!list2) return;
|
|
44695
|
+
const tree = deps.getSidebarView() === "tree";
|
|
44696
|
+
list2.classList.toggle("tree", tree);
|
|
44697
|
+
for (const button of sidebarViewButtons()) {
|
|
44698
|
+
const active = button.dataset.view === (tree ? "tree" : "flat");
|
|
44699
|
+
button.classList.toggle("active", active);
|
|
44700
|
+
button.setAttribute("aria-pressed", String(active));
|
|
44701
|
+
}
|
|
44702
|
+
for (const button of document.querySelectorAll(
|
|
44703
|
+
".sb-tree-action"
|
|
44704
|
+
)) {
|
|
44705
|
+
button.disabled = !tree;
|
|
44706
|
+
}
|
|
44707
|
+
if (title) title.textContent = t2.panes.files;
|
|
44708
|
+
const item = selectedWorktree();
|
|
44709
|
+
if (totals) {
|
|
44710
|
+
totals.textContent = item ? t2.files.heading(item.fileCount) : "";
|
|
44711
|
+
}
|
|
44712
|
+
list2.replaceChildren();
|
|
44713
|
+
if (!item) {
|
|
44714
|
+
list2.appendChild(note(t2.panes.selectWorktree));
|
|
44715
|
+
return;
|
|
44716
|
+
}
|
|
44717
|
+
if (!item.fileCount) {
|
|
44718
|
+
list2.appendChild(note(t2.files.none));
|
|
44719
|
+
return;
|
|
44720
|
+
}
|
|
44721
|
+
const shown = visibleFiles(item);
|
|
44722
|
+
if (!shown.length) {
|
|
44723
|
+
list2.appendChild(note(t2.panes.noFileMatch));
|
|
44724
|
+
return;
|
|
44725
|
+
}
|
|
44726
|
+
if (shown.some((entry) => overlapOthers(item, entry).length > 0)) {
|
|
44727
|
+
list2.appendChild(
|
|
44728
|
+
el("li", "worktree-overlap-legend", t2.intro.overlapLegend)
|
|
44729
|
+
);
|
|
44730
|
+
}
|
|
44731
|
+
for (const group of ["uncommitted", "committed"]) {
|
|
44732
|
+
const files = shown.filter((file) => file.origin === group);
|
|
44733
|
+
if (!files.length) continue;
|
|
44734
|
+
list2.appendChild(
|
|
44735
|
+
el(
|
|
44736
|
+
"li",
|
|
44737
|
+
"worktree-file-group",
|
|
44738
|
+
group === "uncommitted" ? t2.files.uncommitted : t2.files.committed
|
|
44739
|
+
)
|
|
44740
|
+
);
|
|
44741
|
+
if (tree) renderTreeInto(list2, item, buildTree(files), 0);
|
|
44742
|
+
else {
|
|
44743
|
+
for (const file of files) {
|
|
44744
|
+
list2.appendChild(fileRow(item, file, 0, file.path));
|
|
44745
|
+
}
|
|
44746
|
+
}
|
|
44747
|
+
}
|
|
44748
|
+
}
|
|
44749
|
+
function onFileListClick(event) {
|
|
44750
|
+
const row = event.target?.closest(
|
|
44751
|
+
".tree-file"
|
|
44752
|
+
);
|
|
44753
|
+
const key = row?.dataset.key;
|
|
44754
|
+
if (!key) return;
|
|
44755
|
+
const shell = document.querySelector(
|
|
44756
|
+
`#diff .gdp-file-shell[data-key="${CSS.escape(key)}"]`
|
|
44757
|
+
);
|
|
44758
|
+
restoredRouteKey = key;
|
|
44759
|
+
shell?.scrollIntoView({ block: "start" });
|
|
44760
|
+
const [origin, ...rest] = key.split(":");
|
|
44761
|
+
navigate(
|
|
44762
|
+
{
|
|
44763
|
+
file: rest.join(":"),
|
|
44764
|
+
origin: origin === "committed" ? "committed" : "uncommitted"
|
|
44765
|
+
},
|
|
44766
|
+
true
|
|
44767
|
+
);
|
|
44768
|
+
}
|
|
44769
|
+
function diffKey(item) {
|
|
44770
|
+
const options = deps.getOptions();
|
|
44771
|
+
return [
|
|
44772
|
+
item?.path || "",
|
|
44773
|
+
options.layout,
|
|
44774
|
+
options.ignoreWs ? "w" : "",
|
|
44775
|
+
options.hideTests ? "t" : "",
|
|
44776
|
+
options.syntax ? "s" : "",
|
|
44777
|
+
fileFilter
|
|
44778
|
+
].join("|");
|
|
44779
|
+
}
|
|
44780
|
+
async function loadShell(item, file, shell) {
|
|
44781
|
+
const seq = lifecycle;
|
|
44782
|
+
const renderKey = diffKey(item);
|
|
44783
|
+
const t2 = text3();
|
|
44784
|
+
const body = shell.querySelector(".gdp-shell-body");
|
|
44785
|
+
if (!body) return;
|
|
44786
|
+
const params = new URLSearchParams({
|
|
44787
|
+
path: item.path,
|
|
44788
|
+
file: file.path,
|
|
44789
|
+
origin: file.origin
|
|
44790
|
+
});
|
|
44791
|
+
if (file.status === "U") params.set("untracked", "1");
|
|
44792
|
+
if (deps.getOptions().ignoreWs) params.set("ignore_ws", "1");
|
|
44793
|
+
try {
|
|
44794
|
+
const res = await deps.trackLoad(
|
|
44795
|
+
fetch(`/_worktree/diff?${params.toString()}`).then(async (response) => {
|
|
44796
|
+
if (!response.ok) {
|
|
44797
|
+
throw new Error(await response.text() || `${response.status}`);
|
|
44798
|
+
}
|
|
44799
|
+
return await response.json();
|
|
44800
|
+
})
|
|
44801
|
+
);
|
|
44802
|
+
if (!isCurrent(seq) || !shell.isConnected || diffKey(item) !== renderKey) {
|
|
44803
|
+
return;
|
|
44804
|
+
}
|
|
44805
|
+
const options = deps.getOptions();
|
|
44806
|
+
const hljs = options.syntax ? await deps.loadHljs() : null;
|
|
44807
|
+
if (!isCurrent(seq) || !shell.isConnected || diffKey(item) !== renderKey) {
|
|
44808
|
+
return;
|
|
44809
|
+
}
|
|
44810
|
+
body.replaceChildren();
|
|
44811
|
+
if (!res.diff.trim()) {
|
|
44812
|
+
body.appendChild(el("div", "gdp-info", t2.panes.diffEmpty));
|
|
44813
|
+
} else {
|
|
44814
|
+
const head = shell.querySelector(".gdp-shell-header");
|
|
44815
|
+
if (head) head.style.display = "none";
|
|
44816
|
+
if (res.truncated) {
|
|
44817
|
+
body.appendChild(
|
|
44818
|
+
el(
|
|
44819
|
+
"div",
|
|
44820
|
+
"gdp-info",
|
|
44821
|
+
t2.panes.diffTruncated(res.renderedHunks, res.totalHunks)
|
|
44822
|
+
)
|
|
44823
|
+
);
|
|
44824
|
+
}
|
|
44825
|
+
const host = el("div", "");
|
|
44826
|
+
body.appendChild(host);
|
|
44827
|
+
const ui = new window.Diff2HtmlUI(
|
|
44828
|
+
host,
|
|
44829
|
+
res.diff,
|
|
44830
|
+
{
|
|
44831
|
+
drawFileList: false,
|
|
44832
|
+
matching: "lines",
|
|
44833
|
+
// topbar の 統合 / 分割。
|
|
44834
|
+
outputFormat: options.layout,
|
|
44835
|
+
synchronisedScroll: true,
|
|
44836
|
+
// topbar の「構文」。diff2html 自身に塗らせる (Diff ビューアは
|
|
44837
|
+
// 巨大ファイル対策で自前の idle 描画を持つが、こちらは 1 本ぶんの
|
|
44838
|
+
// 変更が対象なのでライブラリに任せる)。
|
|
44839
|
+
highlight: !!hljs,
|
|
44840
|
+
fileListToggle: false,
|
|
44841
|
+
fileContentToggle: false
|
|
44842
|
+
},
|
|
44843
|
+
hljs
|
|
44844
|
+
);
|
|
44845
|
+
ui.draw();
|
|
44846
|
+
}
|
|
44847
|
+
shell.classList.add("loaded");
|
|
44848
|
+
} catch (error2) {
|
|
44849
|
+
if (!isCurrent(seq) || !shell.isConnected) return;
|
|
44850
|
+
body.replaceChildren();
|
|
44851
|
+
const failure = el(
|
|
44852
|
+
"div",
|
|
44853
|
+
"gdp-info",
|
|
44854
|
+
error2 instanceof Error ? error2.message : t2.panes.diffFailed
|
|
44855
|
+
);
|
|
44856
|
+
failure.setAttribute("role", "alert");
|
|
44857
|
+
body.appendChild(failure);
|
|
44858
|
+
shell.classList.add("loaded");
|
|
44859
|
+
}
|
|
44860
|
+
}
|
|
44861
|
+
function renderDiffs() {
|
|
44862
|
+
const t2 = text3();
|
|
44863
|
+
const diff = document.getElementById("diff");
|
|
44864
|
+
if (!diff) return;
|
|
44865
|
+
const item = selectedWorktree();
|
|
44866
|
+
observer?.disconnect();
|
|
44867
|
+
observer = null;
|
|
44868
|
+
restoredRouteKey = null;
|
|
44869
|
+
diff.replaceChildren();
|
|
44870
|
+
if (!item) {
|
|
44871
|
+
if (data && data.worktrees.length === 1) {
|
|
44872
|
+
diff.appendChild(introCard());
|
|
44873
|
+
} else {
|
|
44874
|
+
diff.appendChild(el("div", "gdp-info", t2.panes.selectWorktree));
|
|
44875
|
+
}
|
|
44876
|
+
diffFor = "";
|
|
44877
|
+
return;
|
|
44878
|
+
}
|
|
44879
|
+
if (!item.fileCount) {
|
|
44880
|
+
const card = el("div", "gdp-info worktree-empty-diff");
|
|
44881
|
+
card.appendChild(el("p", "", t2.emptyDiff.title));
|
|
44882
|
+
card.appendChild(el("p", "", t2.emptyDiff.body(item.path)));
|
|
44883
|
+
if (!item.missing && !item.bare) {
|
|
44884
|
+
const buttons = el("span", "worktree-empty-diff-actions");
|
|
44885
|
+
const openFolder = openFolderButton(item, true);
|
|
44886
|
+
if (openFolder) buttons.appendChild(openFolder);
|
|
44887
|
+
buttons.appendChild(copyPathButton(item, true));
|
|
44888
|
+
card.appendChild(buttons);
|
|
44889
|
+
}
|
|
44890
|
+
diff.appendChild(card);
|
|
44891
|
+
diffFor = diffKey(item);
|
|
44892
|
+
return;
|
|
44893
|
+
}
|
|
44894
|
+
const files = visibleFiles(item);
|
|
44895
|
+
if (!files.length) {
|
|
44896
|
+
diff.appendChild(el("div", "gdp-info", t2.panes.noFileMatch));
|
|
44897
|
+
diffFor = diffKey(item);
|
|
44898
|
+
return;
|
|
44899
|
+
}
|
|
44900
|
+
const pending = /* @__PURE__ */ new Map();
|
|
44901
|
+
for (const file of files) {
|
|
44902
|
+
const shell = el("div", "gdp-file-shell");
|
|
44903
|
+
shell.dataset.path = file.path;
|
|
44904
|
+
shell.dataset.key = fileKey(file);
|
|
44905
|
+
shell.dataset.status = file.status;
|
|
44906
|
+
const head = el("div", "gdp-shell-header");
|
|
44907
|
+
head.appendChild(el("span", `status-pill ${file.status}`, file.status));
|
|
44908
|
+
head.appendChild(el("span", "path", file.path));
|
|
44909
|
+
const stats = el("span", "stats");
|
|
44910
|
+
stats.appendChild(el("span", "a", `+${file.additions}`));
|
|
44911
|
+
stats.appendChild(el("span", "d", `−${file.deletions}`));
|
|
44912
|
+
head.appendChild(stats);
|
|
44913
|
+
shell.appendChild(head);
|
|
44914
|
+
const body = el("div", "gdp-shell-body");
|
|
44915
|
+
body.appendChild(el("div", "gdp-info", t2.panes.diffLoading));
|
|
44916
|
+
shell.appendChild(body);
|
|
44917
|
+
diff.appendChild(shell);
|
|
44918
|
+
pending.set(shell, file);
|
|
44919
|
+
}
|
|
44920
|
+
diffFor = diffKey(item);
|
|
44921
|
+
if (typeof IntersectionObserver === "undefined") {
|
|
44922
|
+
for (const [shell, file] of pending) void loadShell(item, file, shell);
|
|
44923
|
+
return;
|
|
44924
|
+
}
|
|
44925
|
+
observer = new IntersectionObserver(
|
|
44926
|
+
(entries) => {
|
|
44927
|
+
for (const entry of entries) {
|
|
44928
|
+
if (!entry.isIntersecting) continue;
|
|
44929
|
+
const shell = entry.target;
|
|
44930
|
+
const file = pending.get(shell);
|
|
44931
|
+
if (!file) continue;
|
|
44932
|
+
pending.delete(shell);
|
|
44933
|
+
observer?.unobserve(shell);
|
|
44934
|
+
void loadShell(item, file, shell);
|
|
44935
|
+
}
|
|
44936
|
+
},
|
|
44937
|
+
{ rootMargin: DIFF_PREFETCH_MARGIN }
|
|
44938
|
+
);
|
|
44939
|
+
for (const shell of pending.keys()) observer.observe(shell);
|
|
44940
|
+
}
|
|
44941
|
+
function render() {
|
|
44942
|
+
renderList();
|
|
44943
|
+
renderFiles();
|
|
44944
|
+
const item = selectedWorktree();
|
|
44945
|
+
if (diffKey(item) !== diffFor) renderDiffs();
|
|
44946
|
+
restoreRouteSelection();
|
|
44947
|
+
}
|
|
44948
|
+
function restoreRouteSelection() {
|
|
44949
|
+
const current = route();
|
|
44950
|
+
if (!current?.file || !current.origin) {
|
|
44951
|
+
restoredRouteKey = null;
|
|
44952
|
+
return;
|
|
44953
|
+
}
|
|
44954
|
+
const key = `${current.origin}:${current.file}`;
|
|
44955
|
+
if (key === restoredRouteKey) return;
|
|
44956
|
+
const shell = document.querySelector(
|
|
44957
|
+
`#diff .gdp-file-shell[data-key="${CSS.escape(key)}"]`
|
|
44958
|
+
);
|
|
44959
|
+
if (!shell) return;
|
|
44960
|
+
restoredRouteKey = key;
|
|
44961
|
+
shell.scrollIntoView({ block: "start" });
|
|
44962
|
+
}
|
|
44963
|
+
return {
|
|
44964
|
+
async enter() {
|
|
44965
|
+
if (deps.getRoute().screen !== "worktree") return;
|
|
44966
|
+
if (mounted) {
|
|
44967
|
+
render();
|
|
44968
|
+
return;
|
|
44969
|
+
}
|
|
44970
|
+
mount();
|
|
44971
|
+
await refresh();
|
|
44972
|
+
},
|
|
44973
|
+
suspend,
|
|
44974
|
+
reload() {
|
|
44975
|
+
if (!mounted) return this.enter();
|
|
44976
|
+
return refresh();
|
|
44977
|
+
},
|
|
44978
|
+
displayOptionsChanged() {
|
|
44979
|
+
if (!mounted) return;
|
|
44980
|
+
diffFor = null;
|
|
44981
|
+
render();
|
|
44982
|
+
},
|
|
44983
|
+
handleSse() {
|
|
44984
|
+
if (!mounted) return;
|
|
44985
|
+
if (sseTimer !== null) window.clearTimeout(sseTimer);
|
|
44986
|
+
sseTimer = window.setTimeout(() => {
|
|
44987
|
+
sseTimer = null;
|
|
44988
|
+
void refresh();
|
|
44989
|
+
}, SSE_REFRESH_DELAY_MS);
|
|
44990
|
+
},
|
|
44991
|
+
localize() {
|
|
44992
|
+
if (!mounted) return;
|
|
44993
|
+
diffFor = null;
|
|
44994
|
+
render();
|
|
44995
|
+
}
|
|
44996
|
+
};
|
|
44997
|
+
}
|
|
44998
|
+
|
|
43140
44999
|
// web-src/app.ts
|
|
43141
45000
|
window.GdpExpandLogic = GdpExpandLogic;
|
|
43142
45001
|
(() => {
|
|
@@ -43310,12 +45169,12 @@ ${formatErrorDetail(error2)}`);
|
|
|
43310
45169
|
}
|
|
43311
45170
|
function setProjectBranch(branch) {
|
|
43312
45171
|
PROJECT_BRANCH = branch;
|
|
43313
|
-
const
|
|
43314
|
-
if (!
|
|
43315
|
-
|
|
43316
|
-
const name =
|
|
45172
|
+
const el2 = document.querySelector("#project-branch");
|
|
45173
|
+
if (!el2) return;
|
|
45174
|
+
el2.hidden = !branch;
|
|
45175
|
+
const name = el2.querySelector(".project-branch-name");
|
|
43317
45176
|
if (name) name.textContent = branch;
|
|
43318
|
-
|
|
45177
|
+
el2.title = branch ? `Current branch: ${branch}` : "";
|
|
43319
45178
|
}
|
|
43320
45179
|
function mergeLocalSettings(patch) {
|
|
43321
45180
|
const next = { ...APP_SETTINGS };
|
|
@@ -44209,6 +46068,7 @@ ${error2.stack}` : ""}`
|
|
|
44209
46068
|
history: "History",
|
|
44210
46069
|
journal: "Work Log",
|
|
44211
46070
|
database: "Datastores",
|
|
46071
|
+
worktree: "Worktrees",
|
|
44212
46072
|
tools: "Tools",
|
|
44213
46073
|
help: "Settings & Help"
|
|
44214
46074
|
},
|
|
@@ -44544,6 +46404,7 @@ ${error2.stack}` : ""}`
|
|
|
44544
46404
|
history: "履歴",
|
|
44545
46405
|
journal: "ワークログ",
|
|
44546
46406
|
database: "データストア",
|
|
46407
|
+
worktree: "作業ツリー",
|
|
44547
46408
|
tools: "ツール",
|
|
44548
46409
|
help: "設定・ヘルプ"
|
|
44549
46410
|
},
|
|
@@ -44877,8 +46738,8 @@ ${error2.stack}` : ""}`
|
|
|
44877
46738
|
return UI_TEXT[STATE.language];
|
|
44878
46739
|
}
|
|
44879
46740
|
function setElementText(selector, text3) {
|
|
44880
|
-
const
|
|
44881
|
-
if (
|
|
46741
|
+
const el2 = document.querySelector(selector);
|
|
46742
|
+
if (el2) el2.textContent = text3;
|
|
44882
46743
|
}
|
|
44883
46744
|
function setButtonLabel(button, text3) {
|
|
44884
46745
|
if (button) button.textContent = text3;
|
|
@@ -45064,6 +46925,7 @@ ${error2.stack}` : ""}`
|
|
|
45064
46925
|
});
|
|
45065
46926
|
relocalizeHistory?.();
|
|
45066
46927
|
relocalizeJournal?.();
|
|
46928
|
+
relocalizeWorktree?.();
|
|
45067
46929
|
relocalizeViewerSettings?.();
|
|
45068
46930
|
SOURCE_VIEW.localize();
|
|
45069
46931
|
setElementText(".annotation-panel-head strong", text3.annotations.title);
|
|
@@ -45097,6 +46959,7 @@ ${error2.stack}` : ""}`
|
|
|
45097
46959
|
}
|
|
45098
46960
|
let relocalizeHistory = null;
|
|
45099
46961
|
let relocalizeJournal = null;
|
|
46962
|
+
let relocalizeWorktree = null;
|
|
45100
46963
|
let relocalizeTools = null;
|
|
45101
46964
|
let relocalizeViewerSettings = null;
|
|
45102
46965
|
let relocalizeTerminal = null;
|
|
@@ -45125,14 +46988,14 @@ ${error2.stack}` : ""}`
|
|
|
45125
46988
|
}
|
|
45126
46989
|
}
|
|
45127
46990
|
function setStatus(s2) {
|
|
45128
|
-
const
|
|
45129
|
-
|
|
45130
|
-
if (s2)
|
|
46991
|
+
const el2 = $("#status");
|
|
46992
|
+
el2.classList.remove("live", "refreshing", "error");
|
|
46993
|
+
if (s2) el2.classList.add(s2);
|
|
45131
46994
|
const text3 = uiText();
|
|
45132
46995
|
const label = s2 === "live" ? text3.global.statusLive : s2 === "refreshing" ? text3.global.statusLoading : s2 === "error" ? text3.global.statusError : text3.global.statusIdle;
|
|
45133
|
-
const labelEl =
|
|
46996
|
+
const labelEl = el2.querySelector(".status-label");
|
|
45134
46997
|
if (labelEl) labelEl.textContent = label;
|
|
45135
|
-
|
|
46998
|
+
el2.setAttribute("aria-label", label);
|
|
45136
46999
|
updateNetworkActivity();
|
|
45137
47000
|
}
|
|
45138
47001
|
function applyTheme() {
|
|
@@ -45196,7 +47059,8 @@ ${error2.stack}` : ""}`
|
|
|
45196
47059
|
}
|
|
45197
47060
|
function routeCanUseSyntaxHighlighter(route = STATE.route) {
|
|
45198
47061
|
if (!STATE.syntaxHighlight) return false;
|
|
45199
|
-
if (route.screen === "diff" || route.screen === "history"
|
|
47062
|
+
if (route.screen === "diff" || route.screen === "history" || route.screen === "worktree")
|
|
47063
|
+
return true;
|
|
45200
47064
|
return route.screen === "file" && sourceInternalPathKind(route.path) === null;
|
|
45201
47065
|
}
|
|
45202
47066
|
function ensureSyntaxHighlighterForRoute() {
|
|
@@ -45204,6 +47068,7 @@ ${error2.stack}` : ""}`
|
|
|
45204
47068
|
loadSyntaxHighlighter().then((hljsRef) => {
|
|
45205
47069
|
if (!hljsRef) return;
|
|
45206
47070
|
rerenderLoadedDiffs();
|
|
47071
|
+
WORKTREE_VIEW?.displayOptionsChanged();
|
|
45207
47072
|
});
|
|
45208
47073
|
}
|
|
45209
47074
|
function setLayout(layout, persist = true) {
|
|
@@ -45223,9 +47088,10 @@ ${error2.stack}` : ""}`
|
|
|
45223
47088
|
}
|
|
45224
47089
|
scheduleIdleHighlight(card, file);
|
|
45225
47090
|
});
|
|
47091
|
+
WORKTREE_VIEW?.displayOptionsChanged();
|
|
45226
47092
|
}
|
|
45227
|
-
function setChevronIcon(
|
|
45228
|
-
|
|
47093
|
+
function setChevronIcon(el2) {
|
|
47094
|
+
el2.innerHTML = '<svg class="octicon octicon-chevron-down" viewBox="0 0 12 12" width="12" height="12" fill="currentColor" aria-hidden="true"><path fill="currentColor" d="' + CHEVRON_DOWN_12_PATH + '"></path></svg>';
|
|
45229
47095
|
}
|
|
45230
47096
|
function scopeOmitSourceLabel() {
|
|
45231
47097
|
return savedScopeOmitDirs() != null || savedScopeExcludeNames() != null ? uiText().settings.browserOverride : uiText().settings.serverDefault;
|
|
@@ -45506,6 +47372,7 @@ ${error2.stack}` : ""}`
|
|
|
45506
47372
|
}
|
|
45507
47373
|
let ANNOTATIONS_UI = null;
|
|
45508
47374
|
let JOURNAL_VIEW = null;
|
|
47375
|
+
let WORKTREE_VIEW = null;
|
|
45509
47376
|
function applyInlineAnnotations() {
|
|
45510
47377
|
ANNOTATIONS_UI?.applyInlineAnnotations();
|
|
45511
47378
|
}
|
|
@@ -45546,12 +47413,53 @@ ${error2.stack}` : ""}`
|
|
|
45546
47413
|
);
|
|
45547
47414
|
}
|
|
45548
47415
|
}
|
|
47416
|
+
let fileRouteSignature = null;
|
|
47417
|
+
let fileRouteSignatureSeed = null;
|
|
47418
|
+
let fileRouteSignatureCheck = null;
|
|
47419
|
+
function fileRouteSignatureKey(route) {
|
|
47420
|
+
return `${route.view || "blob"}\0${route.path}\0${route.ref || "worktree"}`;
|
|
47421
|
+
}
|
|
47422
|
+
async function readFileRouteSignature(route) {
|
|
47423
|
+
const info = await REPO_VIEW.loadRawFileInfo({
|
|
47424
|
+
path: route.path,
|
|
47425
|
+
ref: route.ref || "worktree"
|
|
47426
|
+
});
|
|
47427
|
+
return rawFileInfoSignature(info);
|
|
47428
|
+
}
|
|
47429
|
+
function seedFileRouteSignature(route) {
|
|
47430
|
+
const key = fileRouteSignatureKey(route);
|
|
47431
|
+
const seed = trackLoad(readFileRouteSignature(route)).then((sig) => {
|
|
47432
|
+
if (fileRouteSignatureSeed === seed) fileRouteSignatureSeed = null;
|
|
47433
|
+
if (sig === null) return;
|
|
47434
|
+
fileRouteSignature = { key, sig };
|
|
47435
|
+
});
|
|
47436
|
+
fileRouteSignatureSeed = seed;
|
|
47437
|
+
}
|
|
47438
|
+
function refreshFileRouteIfChanged(route) {
|
|
47439
|
+
if (fileRouteSignatureCheck) return;
|
|
47440
|
+
const key = fileRouteSignatureKey(route);
|
|
47441
|
+
const pendingSeed = fileRouteSignatureSeed ?? Promise.resolve();
|
|
47442
|
+
fileRouteSignatureCheck = pendingSeed.then(() => trackLoad(readFileRouteSignature(route))).then((sig) => {
|
|
47443
|
+
fileRouteSignatureCheck = null;
|
|
47444
|
+
if (sig === null) return;
|
|
47445
|
+
const routeNow = STATE.route;
|
|
47446
|
+
if (routeNow.screen !== "file" || !isBlobOrBlameFileRoute(routeNow) || fileRouteSignatureKey(routeNow) !== key)
|
|
47447
|
+
return;
|
|
47448
|
+
if (fileSignatureUnchanged(fileRouteSignature, key, sig)) return;
|
|
47449
|
+
fileRouteSignature = { key, sig };
|
|
47450
|
+
dispatchFileRoute(routeNow, { refresh: true });
|
|
47451
|
+
});
|
|
47452
|
+
fileRouteSignatureCheck.catch(() => {
|
|
47453
|
+
fileRouteSignatureCheck = null;
|
|
47454
|
+
});
|
|
47455
|
+
}
|
|
45549
47456
|
function dispatchFileRoute(route, options = {}) {
|
|
45550
47457
|
if (route.view === "blob") {
|
|
45551
47458
|
setStatus("live");
|
|
45552
47459
|
removeFileHistoryShell2();
|
|
45553
47460
|
BLAME_VIEW.removeBlamePage();
|
|
45554
47461
|
applySourceRouteToShell(options);
|
|
47462
|
+
seedFileRouteSignature(route);
|
|
45555
47463
|
return true;
|
|
45556
47464
|
}
|
|
45557
47465
|
if (route.view === "blame") {
|
|
@@ -45559,6 +47467,7 @@ ${error2.stack}` : ""}`
|
|
|
45559
47467
|
cancelActiveSourceLoad("navigation");
|
|
45560
47468
|
removeFileHistoryShell2();
|
|
45561
47469
|
void BLAME_VIEW.renderBlamePage({ path: route.path, ref: route.ref });
|
|
47470
|
+
seedFileRouteSignature(route);
|
|
45562
47471
|
return true;
|
|
45563
47472
|
}
|
|
45564
47473
|
if (route.view === "history") {
|
|
@@ -45608,6 +47517,9 @@ ${error2.stack}` : ""}`
|
|
|
45608
47517
|
if (previousRoute.screen === "journal" && nextRoute.screen !== "journal") {
|
|
45609
47518
|
JOURNAL_VIEW?.suspend();
|
|
45610
47519
|
}
|
|
47520
|
+
if (previousRoute.screen === "worktree" && nextRoute.screen !== "worktree") {
|
|
47521
|
+
WORKTREE_VIEW?.suspend();
|
|
47522
|
+
}
|
|
45611
47523
|
STATE.route = nextRoute;
|
|
45612
47524
|
STATE.from = nextRoute.range.from;
|
|
45613
47525
|
STATE.to = nextRoute.range.to;
|
|
@@ -45634,13 +47546,19 @@ ${error2.stack}` : ""}`
|
|
|
45634
47546
|
removeStandaloneSource();
|
|
45635
47547
|
void JOURNAL_VIEW?.enter();
|
|
45636
47548
|
}
|
|
47549
|
+
if (nextRoute.screen === "worktree") {
|
|
47550
|
+
cancelActiveSourceLoad("navigation");
|
|
47551
|
+
setPageMode();
|
|
47552
|
+
removeStandaloneSource();
|
|
47553
|
+
void WORKTREE_VIEW?.enter();
|
|
47554
|
+
}
|
|
45637
47555
|
}
|
|
45638
|
-
function setQueryHistoryPanelOpen(
|
|
47556
|
+
function setQueryHistoryPanelOpen(open2) {
|
|
45639
47557
|
const panel = document.getElementById("query-history-panel");
|
|
45640
47558
|
if (!panel) return;
|
|
45641
|
-
panel.hidden = !
|
|
45642
|
-
document.body.classList.toggle("query-history-panel-open",
|
|
45643
|
-
if (
|
|
47559
|
+
panel.hidden = !open2;
|
|
47560
|
+
document.body.classList.toggle("query-history-panel-open", open2);
|
|
47561
|
+
if (open2 && ANNOTATIONS_UI) {
|
|
45644
47562
|
ANNOTATIONS_UI.setAnnotationPanelOpen(false);
|
|
45645
47563
|
}
|
|
45646
47564
|
}
|
|
@@ -45679,6 +47597,18 @@ ${error2.stack}` : ""}`
|
|
|
45679
47597
|
"gdp-journal-page",
|
|
45680
47598
|
STATE.route.screen === "journal"
|
|
45681
47599
|
);
|
|
47600
|
+
document.body.classList.toggle(
|
|
47601
|
+
"gdp-worktree-page",
|
|
47602
|
+
STATE.route.screen === "worktree"
|
|
47603
|
+
);
|
|
47604
|
+
document.body.toggleAttribute(
|
|
47605
|
+
"data-content-scrolls-when-docked",
|
|
47606
|
+
STATE.route.screen === "diff" || STATE.route.screen === "history" || STATE.route.screen === "repo" || STATE.route.screen === "file" || STATE.route.screen === "help" || STATE.route.screen === "worktree"
|
|
47607
|
+
);
|
|
47608
|
+
document.body.toggleAttribute(
|
|
47609
|
+
"data-history-list-panel",
|
|
47610
|
+
historyPanelRoute || STATE.route.screen === "worktree"
|
|
47611
|
+
);
|
|
45682
47612
|
const repoTargetWrap = document.querySelector("#repo-target-wrap");
|
|
45683
47613
|
if (!repoSidebarRoute && repoTargetWrap) {
|
|
45684
47614
|
repoTargetWrap.hidden = true;
|
|
@@ -45753,6 +47683,14 @@ ${error2.stack}` : ""}`
|
|
|
45753
47683
|
})
|
|
45754
47684
|
);
|
|
45755
47685
|
}
|
|
47686
|
+
if (link2.dataset.route === "worktree") {
|
|
47687
|
+
link2.href = withOverlayState(
|
|
47688
|
+
buildRoute({
|
|
47689
|
+
screen: "worktree",
|
|
47690
|
+
range: currentRange()
|
|
47691
|
+
})
|
|
47692
|
+
);
|
|
47693
|
+
}
|
|
45756
47694
|
if (link2.dataset.route === "help") {
|
|
45757
47695
|
link2.href = withOverlayState(
|
|
45758
47696
|
buildRoute({
|
|
@@ -45785,7 +47723,9 @@ ${error2.stack}` : ""}`
|
|
|
45785
47723
|
setTimeout(() => {
|
|
45786
47724
|
button?.classList.remove("opened");
|
|
45787
47725
|
}, 1200);
|
|
45788
|
-
|
|
47726
|
+
return true;
|
|
47727
|
+
} catch (error2) {
|
|
47728
|
+
console.error("[code-viewer] failed to open path in OS", error2);
|
|
45789
47729
|
if (button) {
|
|
45790
47730
|
button.classList.add("failed");
|
|
45791
47731
|
button.title = "failed to open in OS";
|
|
@@ -45794,6 +47734,7 @@ ${error2.stack}` : ""}`
|
|
|
45794
47734
|
button.title = oldTitle || "open in OS";
|
|
45795
47735
|
}, 1600);
|
|
45796
47736
|
}
|
|
47737
|
+
return false;
|
|
45797
47738
|
} finally {
|
|
45798
47739
|
if (button) button.disabled = false;
|
|
45799
47740
|
}
|
|
@@ -46316,10 +48257,7 @@ ${error2.stack}` : ""}`
|
|
|
46316
48257
|
moveActiveSidebarItem(e2.key === "ArrowDown" ? 1 : -1);
|
|
46317
48258
|
} else if (e2.key === "Escape") {
|
|
46318
48259
|
if (sbFilter.value) {
|
|
46319
|
-
|
|
46320
|
-
syncSidebarFilterClearButton();
|
|
46321
|
-
flushSidebarFilter();
|
|
46322
|
-
applyFilter();
|
|
48260
|
+
clearSidebarFilter();
|
|
46323
48261
|
} else {
|
|
46324
48262
|
sbFilter.blur();
|
|
46325
48263
|
}
|
|
@@ -46767,6 +48705,9 @@ ${error2.stack}` : ""}`
|
|
|
46767
48705
|
setStatus("live");
|
|
46768
48706
|
return Promise.resolve(null);
|
|
46769
48707
|
}
|
|
48708
|
+
if (STATE.route.screen === "worktree") {
|
|
48709
|
+
return (WORKTREE_VIEW?.reload() ?? Promise.resolve()).then(() => null);
|
|
48710
|
+
}
|
|
46770
48711
|
if (STATE.route.screen === "file" && !(isFileHistoryRoute(STATE.route) && activeHistoryPathFilter) && // load() is by definition a reload (topbar Reload button, ignore-ws
|
|
46771
48712
|
// toggle, catch-up after SSE reconnect) - bypass the idempotent-mount
|
|
46772
48713
|
// guard so the blob view actually refetches, matching the pre-guard
|
|
@@ -46833,6 +48774,8 @@ ${error2.stack}` : ""}`
|
|
|
46833
48774
|
} else if (STATE.route.screen === "journal") {
|
|
46834
48775
|
setStatus("live");
|
|
46835
48776
|
void JOURNAL_VIEW?.enter();
|
|
48777
|
+
} else if (STATE.route.screen === "worktree") {
|
|
48778
|
+
void WORKTREE_VIEW?.enter();
|
|
46836
48779
|
} else load();
|
|
46837
48780
|
syncLineRefPill();
|
|
46838
48781
|
syncDoctorSheetFromUrl();
|
|
@@ -46975,9 +48918,9 @@ ${error2.stack}` : ""}`
|
|
|
46975
48918
|
function isDoctorOverlayOpen() {
|
|
46976
48919
|
return parseDoctorOverlay(window.location.pathname, window.location.search);
|
|
46977
48920
|
}
|
|
46978
|
-
function updateUrlForDoctorOverlay(
|
|
48921
|
+
function updateUrlForDoctorOverlay(open2) {
|
|
46979
48922
|
const current = window.location.pathname + window.location.search;
|
|
46980
|
-
const next = withDoctorOverlay(current,
|
|
48923
|
+
const next = withDoctorOverlay(current, open2);
|
|
46981
48924
|
if (next !== current) {
|
|
46982
48925
|
history.replaceState(history.state, "", next + window.location.hash);
|
|
46983
48926
|
}
|
|
@@ -46996,9 +48939,9 @@ ${error2.stack}` : ""}`
|
|
|
46996
48939
|
}
|
|
46997
48940
|
function syncDoctorSheetFromUrl() {
|
|
46998
48941
|
const shouldOpen = isDoctorOverlayOpen();
|
|
46999
|
-
const
|
|
47000
|
-
if (shouldOpen && !
|
|
47001
|
-
else if (!shouldOpen &&
|
|
48942
|
+
const open2 = DOCTOR_VIEW.isOpen();
|
|
48943
|
+
if (shouldOpen && !open2) void DOCTOR_VIEW.open();
|
|
48944
|
+
else if (!shouldOpen && open2) DOCTOR_VIEW.close();
|
|
47002
48945
|
}
|
|
47003
48946
|
document.getElementById("doctor-sheet-overlay")?.addEventListener("click", () => closeDoctorSheet());
|
|
47004
48947
|
document.addEventListener("keydown", (event) => {
|
|
@@ -47030,10 +48973,10 @@ ${error2.stack}` : ""}`
|
|
|
47030
48973
|
function syncAppPanel() {
|
|
47031
48974
|
const tools = parseToolsOverlay(window.location.search) !== null;
|
|
47032
48975
|
const terminal = parseTerminalOverlay(window.location.search) !== null;
|
|
47033
|
-
const
|
|
48976
|
+
const open2 = tools || terminal;
|
|
47034
48977
|
const panel = document.getElementById("app-panel");
|
|
47035
48978
|
if (panel) {
|
|
47036
|
-
panel.classList.toggle("app-panel-open",
|
|
48979
|
+
panel.classList.toggle("app-panel-open", open2);
|
|
47037
48980
|
}
|
|
47038
48981
|
for (const [id, selected] of [
|
|
47039
48982
|
["#panel-tab-tools", tools],
|
|
@@ -47121,10 +49064,10 @@ ${error2.stack}` : ""}`
|
|
|
47121
49064
|
}
|
|
47122
49065
|
function syncToolsSheetFromUrl() {
|
|
47123
49066
|
const tool = openToolsOverlay();
|
|
47124
|
-
const
|
|
47125
|
-
if (tool && (!
|
|
49067
|
+
const open2 = TOOLS_VIEW.isOpen();
|
|
49068
|
+
if (tool && (!open2 || TOOLS_VIEW.getActiveTool() !== tool))
|
|
47126
49069
|
void TOOLS_VIEW.open(tool);
|
|
47127
|
-
else if (!tool &&
|
|
49070
|
+
else if (!tool && open2) TOOLS_VIEW.close();
|
|
47128
49071
|
syncAppPanel();
|
|
47129
49072
|
}
|
|
47130
49073
|
const TERMINAL_VIEW = createTerminalView({
|
|
@@ -47167,11 +49110,11 @@ ${error2.stack}` : ""}`
|
|
|
47167
49110
|
}
|
|
47168
49111
|
function syncTerminalSheetFromUrl() {
|
|
47169
49112
|
const state = parseTerminalOverlay(window.location.search);
|
|
47170
|
-
const
|
|
49113
|
+
const open2 = TERMINAL_VIEW.isOpen();
|
|
47171
49114
|
const target = state === "open" ? null : state;
|
|
47172
|
-
if (state && (!
|
|
49115
|
+
if (state && (!open2 || target && TERMINAL_VIEW.getActiveTarget() !== target)) {
|
|
47173
49116
|
void TERMINAL_VIEW.open(target);
|
|
47174
|
-
} else if (!state &&
|
|
49117
|
+
} else if (!state && open2) {
|
|
47175
49118
|
TERMINAL_VIEW.close();
|
|
47176
49119
|
}
|
|
47177
49120
|
syncAppPanel();
|
|
@@ -47187,6 +49130,30 @@ ${error2.stack}` : ""}`
|
|
|
47187
49130
|
setStatus
|
|
47188
49131
|
});
|
|
47189
49132
|
relocalizeJournal = () => JOURNAL_VIEW?.localize();
|
|
49133
|
+
WORKTREE_VIEW = createWorktreeView({
|
|
49134
|
+
getRoute: () => STATE.route,
|
|
49135
|
+
// topbar のトグルは Diff ビューアと同じものを使う。値の出所も同じ STATE。
|
|
49136
|
+
getOptions: () => ({
|
|
49137
|
+
layout: STATE.layout,
|
|
49138
|
+
ignoreWs: STATE.ignoreWs,
|
|
49139
|
+
hideTests: STATE.hideTests,
|
|
49140
|
+
syntax: STATE.syntaxHighlight
|
|
49141
|
+
}),
|
|
49142
|
+
isTestPath: isTestFilePath,
|
|
49143
|
+
getSidebarView: () => STATE.sbView,
|
|
49144
|
+
// ハイライタは遅延バンドル。差分を描く直前に読み込ませる。
|
|
49145
|
+
loadHljs: loadSyntaxHighlighter,
|
|
49146
|
+
setRoute,
|
|
49147
|
+
currentRange,
|
|
49148
|
+
trackLoad,
|
|
49149
|
+
getText: () => worktreeText(STATE.language),
|
|
49150
|
+
setPageMode,
|
|
49151
|
+
syncHeaderMenu,
|
|
49152
|
+
setStatus,
|
|
49153
|
+
createOpenPathButton,
|
|
49154
|
+
openPathInOs: (path, kind) => openPathInOs(path, kind)
|
|
49155
|
+
});
|
|
49156
|
+
relocalizeWorktree = () => WORKTREE_VIEW?.localize();
|
|
47190
49157
|
const DATABASE_VIEW = createDatabaseView({
|
|
47191
49158
|
setRoute,
|
|
47192
49159
|
setPageMode,
|
|
@@ -47245,6 +49212,8 @@ ${error2.stack}` : ""}`
|
|
|
47245
49212
|
DATABASE_VIEW.suspend();
|
|
47246
49213
|
if (previousRoute.screen === "journal" && nextRoute.screen !== "journal")
|
|
47247
49214
|
JOURNAL_VIEW?.suspend();
|
|
49215
|
+
if (previousRoute.screen === "worktree" && nextRoute.screen !== "worktree")
|
|
49216
|
+
WORKTREE_VIEW?.suspend();
|
|
47248
49217
|
if (isHistoryPanelRoute(previousRoute) && !isHistoryPanelRoute(nextRoute))
|
|
47249
49218
|
HISTORY_VIEW.leaveHistory();
|
|
47250
49219
|
if (isHistoryPanelRoute(previousRoute) && !isHistoryPanelRoute(nextRoute))
|
|
@@ -47314,6 +49283,13 @@ ${error2.stack}` : ""}`
|
|
|
47314
49283
|
setStatus("live");
|
|
47315
49284
|
return;
|
|
47316
49285
|
}
|
|
49286
|
+
if (STATE.route.screen === "worktree") {
|
|
49287
|
+
cancelActiveSourceLoad("navigation");
|
|
49288
|
+
setPageMode();
|
|
49289
|
+
removeStandaloneSource();
|
|
49290
|
+
void WORKTREE_VIEW?.enter();
|
|
49291
|
+
return;
|
|
49292
|
+
}
|
|
47317
49293
|
if (STATE.route.screen !== "file") {
|
|
47318
49294
|
cancelActiveSourceLoad("navigation");
|
|
47319
49295
|
setPageMode();
|
|
@@ -47365,6 +49341,7 @@ ${error2.stack}` : ""}`
|
|
|
47365
49341
|
ensureSyntaxHighlighterForRoute();
|
|
47366
49342
|
} else {
|
|
47367
49343
|
rerenderLoadedDiffs();
|
|
49344
|
+
WORKTREE_VIEW?.displayOptionsChanged();
|
|
47368
49345
|
}
|
|
47369
49346
|
}
|
|
47370
49347
|
setHighlightButton(STATE.syntaxHighlight && getHljs() ? "loaded" : "idle");
|
|
@@ -47389,6 +49366,7 @@ ${error2.stack}` : ""}`
|
|
|
47389
49366
|
else updateTreeDirVisibility();
|
|
47390
49367
|
if (typeof applyViewedState === "function") applyViewedState();
|
|
47391
49368
|
applyHideTestsToMeta();
|
|
49369
|
+
WORKTREE_VIEW?.displayOptionsChanged();
|
|
47392
49370
|
}
|
|
47393
49371
|
function visibleDiffMetaForBrief(meta) {
|
|
47394
49372
|
if (!meta.totals) return meta;
|
|
@@ -47441,7 +49419,7 @@ ${error2.stack}` : ""}`
|
|
|
47441
49419
|
getFiles: () => STATE.files,
|
|
47442
49420
|
getRoute: () => STATE.route,
|
|
47443
49421
|
getAnnotationPanelOpen: () => APP_SETTINGS.annotationPanelOpen === true,
|
|
47444
|
-
setAnnotationPanelOpenState: (
|
|
49422
|
+
setAnnotationPanelOpenState: (open2) => patchSettings({ annotationPanelOpen: open2 }),
|
|
47445
49423
|
getAnnotationPanelWidth: () => APP_SETTINGS.annotationPanelWidth,
|
|
47446
49424
|
setAnnotationPanelWidth: (width) => patchSettings({ annotationPanelWidth: width }),
|
|
47447
49425
|
getAnnotationFollow: () => APP_SETTINGS.annotationFollow !== false,
|
|
@@ -47502,7 +49480,7 @@ ${error2.stack}` : ""}`
|
|
|
47502
49480
|
$,
|
|
47503
49481
|
getActiveSessionEntries: () => ANNOTATIONS_UI?.getActiveSessionEntries() ?? [],
|
|
47504
49482
|
openAnnotationEntry: (id) => ANNOTATIONS_UI ? ANNOTATIONS_UI.openAnnotationEntry(id) : Promise.resolve(),
|
|
47505
|
-
setAnnotationPanelOpen: (
|
|
49483
|
+
setAnnotationPanelOpen: (open2) => ANNOTATIONS_UI?.setAnnotationPanelOpen(open2),
|
|
47506
49484
|
onAnnotationsChanged: (cb) => ANNOTATIONS_UI?.onAnnotationsChanged(cb),
|
|
47507
49485
|
onAnnotationOpened: (cb) => ANNOTATIONS_UI?.onAnnotationOpened(cb),
|
|
47508
49486
|
getActiveAnnotationId: () => ANNOTATIONS_UI ? ANNOTATIONS_UI.getActiveAnnotationId() : null,
|
|
@@ -47661,7 +49639,7 @@ ${error2.stack}` : ""}`
|
|
|
47661
49639
|
if (isBlobOrBlameFileRoute(route)) {
|
|
47662
49640
|
const viewingPath = route.path;
|
|
47663
49641
|
if (viewingPath && !changedPathsCoverPath(paths, viewingPath)) return;
|
|
47664
|
-
|
|
49642
|
+
refreshFileRouteIfChanged(route);
|
|
47665
49643
|
return;
|
|
47666
49644
|
}
|
|
47667
49645
|
if (route.screen === "repo") {
|
|
@@ -47745,6 +49723,7 @@ ${error2.stack}` : ""}`
|
|
|
47745
49723
|
}
|
|
47746
49724
|
}
|
|
47747
49725
|
if (isHistoryPanelRoute(STATE.route)) HISTORY_VIEW.notePossibleUpdate();
|
|
49726
|
+
if (STATE.route.screen === "worktree") WORKTREE_VIEW?.handleSse();
|
|
47748
49727
|
scheduleSseLoad(paths);
|
|
47749
49728
|
});
|
|
47750
49729
|
es.addEventListener("watch-limit", (event) => {
|