@youtyan/code-viewer 0.6.1 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -4
- package/dist/code-viewer.js +57 -6
- package/package.json +1 -1
- package/web/app.js +2040 -261
- package/web/index.html +40 -13
- package/web/style.css +786 -41
package/web/app.js
CHANGED
|
@@ -21,6 +21,48 @@
|
|
|
21
21
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
22
22
|
});
|
|
23
23
|
|
|
24
|
+
// web-src/core/diff-file-kinds.ts
|
|
25
|
+
var HEAVY_SIZE_CLASSES = new Set(["medium", "large", "huge"]);
|
|
26
|
+
function classifyDiffFileKind(file) {
|
|
27
|
+
const status = (file.status || "")[0]?.toUpperCase();
|
|
28
|
+
const heavy = HEAVY_SIZE_CLASSES.has(file.size_class || "");
|
|
29
|
+
const media = !!file.media_kind;
|
|
30
|
+
return {
|
|
31
|
+
added: status === "A",
|
|
32
|
+
deleted: status === "D",
|
|
33
|
+
renamed: status === "R",
|
|
34
|
+
heavy,
|
|
35
|
+
binary: !media && (file.size_class === "binary" || !!file.binary),
|
|
36
|
+
media
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function summarizeDiffFileKinds(files) {
|
|
40
|
+
const counts = {
|
|
41
|
+
added: 0,
|
|
42
|
+
deleted: 0,
|
|
43
|
+
renamed: 0,
|
|
44
|
+
heavy: 0,
|
|
45
|
+
binary: 0,
|
|
46
|
+
media: 0
|
|
47
|
+
};
|
|
48
|
+
for (const file of files) {
|
|
49
|
+
const kind = classifyDiffFileKind(file);
|
|
50
|
+
if (kind.added)
|
|
51
|
+
counts.added++;
|
|
52
|
+
if (kind.deleted)
|
|
53
|
+
counts.deleted++;
|
|
54
|
+
if (kind.renamed)
|
|
55
|
+
counts.renamed++;
|
|
56
|
+
if (kind.heavy)
|
|
57
|
+
counts.heavy++;
|
|
58
|
+
if (kind.binary)
|
|
59
|
+
counts.binary++;
|
|
60
|
+
if (kind.media)
|
|
61
|
+
counts.media++;
|
|
62
|
+
}
|
|
63
|
+
return counts;
|
|
64
|
+
}
|
|
65
|
+
|
|
24
66
|
// web-src/core/file-path-copy.ts
|
|
25
67
|
function filePathClipboardText(path) {
|
|
26
68
|
return path || "";
|
|
@@ -55,6 +97,13 @@ ${lines.join(`
|
|
|
55
97
|
|
|
56
98
|
// web-src/core/ai-context-copy.ts
|
|
57
99
|
var AI_CONTEXT_LARGE_SELECTION_LINE_THRESHOLD = 300;
|
|
100
|
+
var DATABASE_QUERY_SQL_MAX_CHARS = 200;
|
|
101
|
+
function truncateOneLine(text, maxChars) {
|
|
102
|
+
const collapsed = text.replace(/\s+/g, " ").trim();
|
|
103
|
+
if (collapsed.length <= maxChars)
|
|
104
|
+
return collapsed;
|
|
105
|
+
return `${collapsed.slice(0, maxChars)}...`;
|
|
106
|
+
}
|
|
58
107
|
function lineRange(line) {
|
|
59
108
|
return typeof line === "number" ? { start: line, end: line } : { start: line.start, end: line.end };
|
|
60
109
|
}
|
|
@@ -104,13 +153,14 @@ ${lines.join(`
|
|
|
104
153
|
`)}
|
|
105
154
|
\`\`\``;
|
|
106
155
|
}
|
|
107
|
-
function historyLine(route) {
|
|
108
|
-
if (
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
156
|
+
function historyLine(route, diffFrom, diffTo) {
|
|
157
|
+
if (route.commit) {
|
|
158
|
+
const ref = route.ref && route.ref !== "worktree" && route.ref !== "HEAD" ? ` (ref: ${route.ref})` : "";
|
|
159
|
+
return `commit: ${route.commit}${ref}`;
|
|
160
|
+
}
|
|
161
|
+
return `History: ${diffFrom}..${diffTo}${commitOrRefSuffix(route)}`;
|
|
112
162
|
}
|
|
113
|
-
function databaseLine(route) {
|
|
163
|
+
function databaseLine(route, querySql) {
|
|
114
164
|
const parts = [];
|
|
115
165
|
if (route.db)
|
|
116
166
|
parts.push(`db=${route.db}`);
|
|
@@ -123,16 +173,52 @@ ${lines.join(`
|
|
|
123
173
|
if (route.diffBefore && route.diffAfter) {
|
|
124
174
|
parts.push(`snapshot=${route.diffBefore}..${route.diffAfter}`);
|
|
125
175
|
}
|
|
126
|
-
|
|
176
|
+
if (route.tab === "query" && querySql) {
|
|
177
|
+
const sql = truncateOneLine(querySql, DATABASE_QUERY_SQL_MAX_CHARS);
|
|
178
|
+
if (sql)
|
|
179
|
+
parts.push(`sql=${sql}`);
|
|
180
|
+
}
|
|
181
|
+
return parts.length > 0 ? `database: ${parts.join(", ")}` : "database";
|
|
182
|
+
}
|
|
183
|
+
function diffOverviewLine(from, to, meta, viewedFiles) {
|
|
184
|
+
const base = `Diff: ${from}..${to}`;
|
|
185
|
+
if (!meta?.totals)
|
|
186
|
+
return base;
|
|
187
|
+
const parts = [
|
|
188
|
+
`${meta.totals.files} file${meta.totals.files === 1 ? "" : "s"}`,
|
|
189
|
+
`+${meta.totals.additions}/-${meta.totals.deletions}`
|
|
190
|
+
];
|
|
191
|
+
const viewedTotal = meta.files.length;
|
|
192
|
+
if (viewedFiles && viewedTotal > 0) {
|
|
193
|
+
const viewed = meta.files.filter((file) => viewedFiles.has(file.path)).length;
|
|
194
|
+
parts.push(`${viewed}/${viewedTotal} viewed`);
|
|
195
|
+
}
|
|
196
|
+
const kinds = summarizeDiffFileKinds(meta.files);
|
|
197
|
+
const kindParts = [];
|
|
198
|
+
if (kinds.added)
|
|
199
|
+
kindParts.push(`${kinds.added} added`);
|
|
200
|
+
if (kinds.deleted)
|
|
201
|
+
kindParts.push(`${kinds.deleted} deleted`);
|
|
202
|
+
if (kinds.renamed)
|
|
203
|
+
kindParts.push(`${kinds.renamed} renamed`);
|
|
204
|
+
if (kinds.heavy)
|
|
205
|
+
kindParts.push(`${kinds.heavy} heavy`);
|
|
206
|
+
if (kinds.binary)
|
|
207
|
+
kindParts.push(`${kinds.binary} binary`);
|
|
208
|
+
if (kinds.media)
|
|
209
|
+
kindParts.push(`${kinds.media} media`);
|
|
210
|
+
if (kindParts.length > 0)
|
|
211
|
+
parts.push(kindParts.join(", "));
|
|
212
|
+
return `${base} (${parts.join(", ")})`;
|
|
127
213
|
}
|
|
128
214
|
function aiContextClipboardText(snapshot) {
|
|
129
215
|
const { route } = snapshot;
|
|
130
216
|
if (route.screen === "database")
|
|
131
|
-
return databaseLine(route);
|
|
217
|
+
return databaseLine(route, snapshot.databaseQuerySql);
|
|
132
218
|
if (route.screen === "history")
|
|
133
|
-
return historyLine(route);
|
|
219
|
+
return historyLine(route, snapshot.diffFrom, snapshot.diffTo);
|
|
134
220
|
if (route.screen === "diff" && !route.path) {
|
|
135
|
-
return
|
|
221
|
+
return diffOverviewLine(snapshot.diffFrom, snapshot.diffTo, snapshot.diffMeta, snapshot.viewedFiles);
|
|
136
222
|
}
|
|
137
223
|
return referenceLine(route, snapshot.selectionCode);
|
|
138
224
|
}
|
|
@@ -401,6 +487,30 @@ ${lines.join(`
|
|
|
401
487
|
"M7.47 2.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 1 1-1.06 1.06L8 3.81 4.28 7.53a.75.75 0 0 1-1.06-1.06Z",
|
|
402
488
|
"M7.47 6.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 1 1-1.06 1.06L8 7.81l-3.72 3.72a.75.75 0 1 1-1.06-1.06Z"
|
|
403
489
|
];
|
|
490
|
+
var PLAY_16_PATH = "M4.75 3.625a.75.75 0 0 1 1.148-.635l6 3.875a.75.75 0 0 1 0 1.27l-6 3.875A.75.75 0 0 1 4.75 11.375Z";
|
|
491
|
+
var PAUSE_16_PATHS = [
|
|
492
|
+
"M4.75 3A.75.75 0 0 1 5.5 2.25h1A.75.75 0 0 1 7.25 3v10a.75.75 0 0 1-.75.75h-1A.75.75 0 0 1 4.75 13Z",
|
|
493
|
+
"M8.75 3a.75.75 0 0 1 .75-.75h1a.75.75 0 0 1 .75.75v10a.75.75 0 0 1-.75.75h-1a.75.75 0 0 1-.75-.75Z"
|
|
494
|
+
];
|
|
495
|
+
var PREVIOUS_16_PATHS = [
|
|
496
|
+
"M3.75 3a.75.75 0 0 1 .75.75v8.5a.75.75 0 0 1-1.5 0v-8.5A.75.75 0 0 1 3.75 3Z",
|
|
497
|
+
"M12.22 3.22a.749.749 0 0 1 0 1.06L8.5 8l3.72 3.72a.749.749 0 1 1-1.06 1.06L6.91 8.53a.749.749 0 0 1 0-1.06l4.25-4.25a.749.749 0 0 1 1.06 0Z"
|
|
498
|
+
];
|
|
499
|
+
var NEXT_16_PATHS = [
|
|
500
|
+
"M12.25 3a.75.75 0 0 1 .75.75v8.5a.75.75 0 0 1-1.5 0v-8.5a.75.75 0 0 1 .75-.75Z",
|
|
501
|
+
"M3.78 3.22a.749.749 0 0 1 1.06 0l4.25 4.25a.749.749 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.06-1.06L7.5 8 3.78 4.28a.749.749 0 0 1 0-1.06Z"
|
|
502
|
+
];
|
|
503
|
+
var VOLUME_UNMUTED_16_PATHS = [
|
|
504
|
+
"M7.563 2.069A.75.75 0 0 1 8 2.75v10.5a.75.75 0 0 1-1.188.61L3.766 11.5H1.75A1.75 1.75 0 0 1 0 9.75v-3.5C0 5.284.784 4.5 1.75 4.5h2.016l3.046-2.36a.75.75 0 0 1 .751-.071ZM6.5 4.279 4.484 5.841A.75.75 0 0 1 4.025 6H1.75a.25.25 0 0 0-.25.25v3.5c0 .138.112.25.25.25h2.275a.75.75 0 0 1 .459.159L6.5 11.721Z",
|
|
505
|
+
"M10.28 5.22a.749.749 0 0 1 1.06 0 3.93 3.93 0 0 1 0 5.56.749.749 0 1 1-1.06-1.06 2.43 2.43 0 0 0 0-3.44.749.749 0 0 1 0-1.06Z",
|
|
506
|
+
"M12.39 3.11a.749.749 0 0 1 1.06 0 6.91 6.91 0 0 1 0 9.78.749.749 0 0 1-1.06-1.06 5.41 5.41 0 0 0 0-7.66.749.749 0 0 1 0-1.06Z"
|
|
507
|
+
];
|
|
508
|
+
var VOLUME_MUTED_16_PATHS = [
|
|
509
|
+
VOLUME_UNMUTED_16_PATHS[0],
|
|
510
|
+
"M10.28 6.22 11.5 7.44l1.22-1.22a.749.749 0 1 1 1.06 1.06L12.56 8.5l1.22 1.22a.749.749 0 1 1-1.06 1.06L11.5 9.56l-1.22 1.22a.749.749 0 1 1-1.06-1.06l1.22-1.22-1.22-1.22a.749.749 0 1 1 1.06-1.06Z"
|
|
511
|
+
];
|
|
512
|
+
var X_16_PATH = "M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z";
|
|
513
|
+
var SYNC_16_PATH = "M1.705 8.005a.75.75 0 0 1 .834.656 5.5 5.5 0 0 0 9.592 2.97l-1.204-1.204a.25.25 0 0 1 .177-.427h3.646a.25.25 0 0 1 .25.25v3.646a.25.25 0 0 1-.427.177l-1.38-1.38A7.002 7.002 0 0 1 1.05 8.84a.75.75 0 0 1 .656-.834ZM8 2.5a5.487 5.487 0 0 0-4.131 1.869l1.204 1.204A.25.25 0 0 1 4.896 6H1.25A.25.25 0 0 1 1 5.75V2.104a.25.25 0 0 1 .427-.177l1.38 1.38A7.002 7.002 0 0 1 14.95 7.16a.75.75 0 0 1-1.49.178A5.5 5.5 0 0 0 8 2.5Z";
|
|
404
514
|
function iconSvg(className, paths) {
|
|
405
515
|
const pathList = Array.isArray(paths) ? paths : [paths];
|
|
406
516
|
return '<svg class="octicon ' + className + '" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" aria-hidden="true">' + pathList.map((path) => `<path fill="currentColor" d="${path}"></path>`).join("") + "</svg>";
|
|
@@ -409,6 +519,12 @@ ${lines.join(`
|
|
|
409
519
|
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";
|
|
410
520
|
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";
|
|
411
521
|
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";
|
|
522
|
+
var SEARCH_16_PATH = "M10.68 11.74a6 6 0 0 1-7.917-8.984 6 6 0 0 1 8.997 7.905l3.05 3.05a.75.75 0 1 1-1.06 1.06l-3.07-3.03ZM11.5 7a4.499 4.499 0 1 1-8.997 0A4.499 4.499 0 0 1 11.5 7Z";
|
|
523
|
+
var DOWNLOAD_16_PATHS = [
|
|
524
|
+
"M2.75 14A1.75 1.75 0 0 1 1 12.25v-2.5a.75.75 0 0 1 1.5 0v2.5c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25v-2.5a.75.75 0 0 1 1.5 0v2.5A1.75 1.75 0 0 1 13.25 14Z",
|
|
525
|
+
"M7.25 7.689V2a.75.75 0 0 1 1.5 0v5.689l1.97-1.969a.749.749 0 1 1 1.06 1.06l-3.25 3.25a.749.749 0 0 1-1.06 0L4.22 6.78a.749.749 0 1 1 1.06-1.06l1.97 1.969Z"
|
|
526
|
+
];
|
|
527
|
+
var LINK_16_PATH = "m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z";
|
|
412
528
|
|
|
413
529
|
// web-src/core/keyboard.ts
|
|
414
530
|
function isImeComposing(event) {
|
|
@@ -522,7 +638,8 @@ ${lines.join(`
|
|
|
522
638
|
{ action: "toggle-theme", key: "t" },
|
|
523
639
|
{ action: "open-help", key: "?", shift: true },
|
|
524
640
|
{ action: "copy-ai-context", key: "y" },
|
|
525
|
-
{ action: "copy-ai-context-with-code", key: "y", shift: true }
|
|
641
|
+
{ action: "copy-ai-context-with-code", key: "y", shift: true },
|
|
642
|
+
{ action: "next-unviewed-file", key: "n" }
|
|
526
643
|
];
|
|
527
644
|
function resolveKeymapAction(event, context) {
|
|
528
645
|
const key = event.key.toLowerCase();
|
|
@@ -1553,6 +1670,11 @@ ${lines.join(`
|
|
|
1553
1670
|
}
|
|
1554
1671
|
|
|
1555
1672
|
// web-src/views/annotations-player.ts
|
|
1673
|
+
function setIconButton(button, label, iconClass, paths) {
|
|
1674
|
+
button.innerHTML = iconSvg(iconClass, paths);
|
|
1675
|
+
button.title = label;
|
|
1676
|
+
button.setAttribute("aria-label", label);
|
|
1677
|
+
}
|
|
1556
1678
|
function createAnnotationsPlayer(deps) {
|
|
1557
1679
|
const bar = deps.$("#annotation-player");
|
|
1558
1680
|
const toggleBtn = deps.$("#annotation-player-toggle");
|
|
@@ -1609,9 +1731,11 @@ ${lines.join(`
|
|
|
1609
1731
|
}
|
|
1610
1732
|
function render(state) {
|
|
1611
1733
|
bar.classList.toggle("playing", state.status === "playing");
|
|
1612
|
-
toggleBtn.
|
|
1734
|
+
setIconButton(toggleBtn, state.status === "playing" ? "Pause annotation playback" : "Play annotation playback", state.status === "playing" ? "octicon-pause" : "octicon-play", state.status === "playing" ? PAUSE_16_PATHS : PLAY_16_PATH);
|
|
1735
|
+
setIconButton(prevBtn, "Previous annotation", "octicon-skip-back", PREVIOUS_16_PATHS);
|
|
1736
|
+
setIconButton(nextBtn, "Next annotation", "octicon-skip-forward", NEXT_16_PATHS);
|
|
1613
1737
|
progress.textContent = state.status === "idle" || state.index < 0 ? `${state.total}` : `${state.index + 1}/${state.total}`;
|
|
1614
|
-
muteBtn.
|
|
1738
|
+
setIconButton(muteBtn, state.muted ? "Unmute annotation playback" : "Mute annotation playback", state.muted ? "octicon-volume-muted" : "octicon-volume-unmuted", state.muted ? VOLUME_MUTED_16_PATHS : VOLUME_UNMUTED_16_PATHS);
|
|
1615
1739
|
prevBtn.disabled = state.status === "idle";
|
|
1616
1740
|
nextBtn.disabled = state.status === "idle";
|
|
1617
1741
|
}
|
|
@@ -8206,6 +8330,14 @@ ${frontmatter.yaml}
|
|
|
8206
8330
|
const annotationListCountEl = $("#annotation-list-count");
|
|
8207
8331
|
const annotationCaptureDb = $("#annotation-capture-db");
|
|
8208
8332
|
annotationCaptureDb.innerHTML = iconSvg("octicon-plus", PLUS_16_PATH);
|
|
8333
|
+
const annotationDetailPrev = $("#annotation-detail-prev");
|
|
8334
|
+
const annotationDetailNext = $("#annotation-detail-next");
|
|
8335
|
+
annotationDetailPrev.innerHTML = iconSvg("octicon-skip-back", PREVIOUS_16_PATHS);
|
|
8336
|
+
annotationDetailPrev.title = "previous annotation";
|
|
8337
|
+
annotationDetailPrev.setAttribute("aria-label", "previous annotation");
|
|
8338
|
+
annotationDetailNext.innerHTML = iconSvg("octicon-skip-forward", NEXT_16_PATHS);
|
|
8339
|
+
annotationDetailNext.title = "next annotation";
|
|
8340
|
+
annotationDetailNext.setAttribute("aria-label", "next annotation");
|
|
8209
8341
|
function updateDatabaseCaptureButton() {
|
|
8210
8342
|
annotationCaptureDb.hidden = deps.getRoute().screen !== "database";
|
|
8211
8343
|
}
|
|
@@ -8842,11 +8974,10 @@ ${frontmatter.yaml}
|
|
|
8842
8974
|
edit.addEventListener("click", () => {
|
|
8843
8975
|
openAnnotationEditForm(entry);
|
|
8844
8976
|
});
|
|
8845
|
-
|
|
8846
|
-
head?.insertBefore(
|
|
8847
|
-
|
|
8848
|
-
|
|
8849
|
-
$("#annotation-detail-next").disabled = index >= session.entries.length - 1;
|
|
8977
|
+
head?.insertBefore(copyRef, annotationDetailPrev);
|
|
8978
|
+
head?.insertBefore(edit, annotationDetailPrev);
|
|
8979
|
+
annotationDetailPrev.disabled = index <= 0;
|
|
8980
|
+
annotationDetailNext.disabled = index >= session.entries.length - 1;
|
|
8850
8981
|
annotationDetail.hidden = false;
|
|
8851
8982
|
setAnnotationPanelOpen(true);
|
|
8852
8983
|
updateActiveHighlights();
|
|
@@ -9077,10 +9208,10 @@ ${frontmatter.yaml}
|
|
|
9077
9208
|
postAnnotationAction({ action: "clear" });
|
|
9078
9209
|
});
|
|
9079
9210
|
$("#annotation-detail-close").addEventListener("click", hideAnnotationDetail);
|
|
9080
|
-
|
|
9211
|
+
annotationDetailPrev.addEventListener("click", () => {
|
|
9081
9212
|
stepAnnotation(-1);
|
|
9082
9213
|
});
|
|
9083
|
-
|
|
9214
|
+
annotationDetailNext.addEventListener("click", () => {
|
|
9084
9215
|
stepAnnotation(1);
|
|
9085
9216
|
});
|
|
9086
9217
|
$("#annotation-detail-location").addEventListener("click", (e2) => {
|
|
@@ -9659,6 +9790,15 @@ ${frontmatter.yaml}
|
|
|
9659
9790
|
schemaTab: "Schema",
|
|
9660
9791
|
selectDatastore: "Select datastore",
|
|
9661
9792
|
selectSchema: "Select PostgreSQL schema",
|
|
9793
|
+
refreshDatastores: "Refresh datastores",
|
|
9794
|
+
refreshDatastoresShort: "Refresh",
|
|
9795
|
+
refreshDatastoresBusy: "Refreshing...",
|
|
9796
|
+
refreshDatastoresTitle: "Refresh the datastore list",
|
|
9797
|
+
refreshDatastoresUnchanged: "No datastore changes",
|
|
9798
|
+
refreshDatastoresChanged: (added, removed) => [
|
|
9799
|
+
added > 0 ? `+${added} datastore${added === 1 ? "" : "s"}` : "",
|
|
9800
|
+
removed > 0 ? `-${removed} datastore${removed === 1 ? "" : "s"}` : ""
|
|
9801
|
+
].filter(Boolean).join(" / "),
|
|
9662
9802
|
toolbar: "Datastore tools",
|
|
9663
9803
|
query: "Query",
|
|
9664
9804
|
queryTitle: "Query Editor",
|
|
@@ -9674,6 +9814,8 @@ ${frontmatter.yaml}
|
|
|
9674
9814
|
closeTab: (label) => `Close ${label}`,
|
|
9675
9815
|
loadingSchema: "Loading schema…",
|
|
9676
9816
|
noDatastores: "No datastores found",
|
|
9817
|
+
noDatastoresHint: "Start a database service or add a SQLite file, then refresh this list.",
|
|
9818
|
+
noDatastoreTab: "No datastore",
|
|
9677
9819
|
dockerLimitReached: "Docker discovery reached the service limit; some compose services may be hidden.",
|
|
9678
9820
|
inferFkLabel: "Rails FK inference",
|
|
9679
9821
|
inferFkTitle: "Infer FK from Rails-style <name>_id → <names>.id",
|
|
@@ -9683,12 +9825,29 @@ ${frontmatter.yaml}
|
|
|
9683
9825
|
grid: {
|
|
9684
9826
|
searchPlaceholder: "Search all columns…",
|
|
9685
9827
|
columnFilterPlaceholder: (column) => `${column}…`,
|
|
9828
|
+
clearFiltersLabel: "Clear filters",
|
|
9829
|
+
clearFiltersAction: (count) => `Clear ${count} active filter${count === 1 ? "" : "s"}`,
|
|
9830
|
+
refreshLabel: "Reload table",
|
|
9831
|
+
refreshFilteredLabel: "Reload filtered rows",
|
|
9832
|
+
refreshingLabel: "Reloading...",
|
|
9833
|
+
refreshAction: "Reload this table, keeping search and column filters",
|
|
9834
|
+
refreshActionWithFilters: (count) => `Reload this table, keeping ${count} active filter${count === 1 ? "" : "s"}`,
|
|
9835
|
+
refreshResultChanged: (delta, total) => {
|
|
9836
|
+
const abs = Math.abs(delta).toLocaleString();
|
|
9837
|
+
const sign = delta > 0 ? "+" : "-";
|
|
9838
|
+
return `Rows ${sign}${abs} (${total} now)`;
|
|
9839
|
+
},
|
|
9840
|
+
refreshResultUnchanged: (total) => `Rows unchanged (${total})`,
|
|
9686
9841
|
exportAction: "Export",
|
|
9687
9842
|
foreignKeyHint: "Foreign key — click to view related rows",
|
|
9688
9843
|
relatedEmpty: "No matching row in the referenced table",
|
|
9844
|
+
filteredEmptyTitle: (count) => `No rows match ${count} active filter${count === 1 ? "" : "s"}`,
|
|
9845
|
+
filteredEmptyHint: "The table was loaded, but the current search or column filters hide every row.",
|
|
9846
|
+
filteredEmptyAction: "Clear filters",
|
|
9689
9847
|
statusRows: (n2) => `${n2} rows`,
|
|
9690
9848
|
statusSort: (column, dir) => `Sort: ${column} ${dir}`,
|
|
9691
|
-
statusFilters: (n2) => `${n2} filter(s)
|
|
9849
|
+
statusFilters: (n2) => `${n2} filter(s)`,
|
|
9850
|
+
statusRefreshing: (filters) => filters > 0 ? `Reloading with ${filters} active filter${filters === 1 ? "" : "s"}…` : "Reloading current table…"
|
|
9692
9851
|
},
|
|
9693
9852
|
edit: {
|
|
9694
9853
|
editMode: "Edit",
|
|
@@ -9712,6 +9871,9 @@ ${frontmatter.yaml}
|
|
|
9712
9871
|
indexes: "Indexes",
|
|
9713
9872
|
triggers: "Triggers",
|
|
9714
9873
|
ddl: "DDL",
|
|
9874
|
+
refreshLabel: "Refresh schema",
|
|
9875
|
+
refreshAction: "Refresh this table schema",
|
|
9876
|
+
refreshingLabel: "Refreshing...",
|
|
9715
9877
|
copyDdl: "Copy DDL",
|
|
9716
9878
|
copied: "Copied!",
|
|
9717
9879
|
colName: "Column",
|
|
@@ -9749,8 +9911,10 @@ ${frontmatter.yaml}
|
|
|
9749
9911
|
statusExplain: (ms) => `Explain (${ms}ms)`
|
|
9750
9912
|
},
|
|
9751
9913
|
history: {
|
|
9752
|
-
refresh: "Refresh",
|
|
9753
|
-
refreshTitle: "Refresh history",
|
|
9914
|
+
refresh: "Refresh history",
|
|
9915
|
+
refreshTitle: "Refresh query history",
|
|
9916
|
+
refreshResultAdded: (count) => `+${count} queries`,
|
|
9917
|
+
refreshResultUnchanged: "No new queries",
|
|
9754
9918
|
clearAll: "Clear All",
|
|
9755
9919
|
clearTitle: "Delete all query history",
|
|
9756
9920
|
selectPlaceholder: "Select a query to view details",
|
|
@@ -9761,6 +9925,10 @@ ${frontmatter.yaml}
|
|
|
9761
9925
|
delete: "Delete",
|
|
9762
9926
|
confirmDelete: "Confirm delete",
|
|
9763
9927
|
confirmClear: "Confirm clear",
|
|
9928
|
+
executorAi: "AI",
|
|
9929
|
+
executorUser: "User",
|
|
9930
|
+
rowsLabel: (rows, truncated) => `${rows}${truncated ? "+" : ""} rows`,
|
|
9931
|
+
elapsedLabel: (ms) => `${ms}ms`,
|
|
9764
9932
|
truncatedRows: (saved, total) => `Showing ${saved} of ${total} rows`
|
|
9765
9933
|
},
|
|
9766
9934
|
sessionLog: {
|
|
@@ -9944,6 +10112,15 @@ ${frontmatter.yaml}
|
|
|
9944
10112
|
schemaTab: "スキーマ",
|
|
9945
10113
|
selectDatastore: "データストアを選択",
|
|
9946
10114
|
selectSchema: "PostgreSQL スキーマを選択",
|
|
10115
|
+
refreshDatastores: "データストアを更新",
|
|
10116
|
+
refreshDatastoresShort: "更新",
|
|
10117
|
+
refreshDatastoresBusy: "更新中...",
|
|
10118
|
+
refreshDatastoresTitle: "データストア一覧を更新",
|
|
10119
|
+
refreshDatastoresUnchanged: "データストアに変化なし",
|
|
10120
|
+
refreshDatastoresChanged: (added, removed) => [
|
|
10121
|
+
added > 0 ? `+${added} データストア` : "",
|
|
10122
|
+
removed > 0 ? `-${removed} データストア` : ""
|
|
10123
|
+
].filter(Boolean).join(" / "),
|
|
9947
10124
|
toolbar: "データストアツール",
|
|
9948
10125
|
query: "クエリ",
|
|
9949
10126
|
queryTitle: "クエリエディタ",
|
|
@@ -9959,6 +10136,8 @@ ${frontmatter.yaml}
|
|
|
9959
10136
|
closeTab: (label) => `${label} を閉じる`,
|
|
9960
10137
|
loadingSchema: "スキーマを読み込み中…",
|
|
9961
10138
|
noDatastores: "データストアが見つかりません",
|
|
10139
|
+
noDatastoresHint: "DB サービスを起動するか SQLite ファイルを追加してから、一覧を更新してください。",
|
|
10140
|
+
noDatastoreTab: "未検出",
|
|
9962
10141
|
dockerLimitReached: "Docker のサービス数が上限に達しました。一部の compose サービスは表示されていない可能性があります。",
|
|
9963
10142
|
inferFkLabel: "Rails FK 推測",
|
|
9964
10143
|
inferFkTitle: "Rails 命名規約 (<name>_id → <names>.id) から FK を推測",
|
|
@@ -9968,12 +10147,29 @@ ${frontmatter.yaml}
|
|
|
9968
10147
|
grid: {
|
|
9969
10148
|
searchPlaceholder: "全カラムを検索…",
|
|
9970
10149
|
columnFilterPlaceholder: (column) => `${column}…`,
|
|
10150
|
+
clearFiltersLabel: "フィルタ解除",
|
|
10151
|
+
clearFiltersAction: (count) => `有効なフィルタ ${count} 件を解除`,
|
|
10152
|
+
refreshLabel: "表を再読込",
|
|
10153
|
+
refreshFilteredLabel: "絞り込み再読込",
|
|
10154
|
+
refreshingLabel: "更新中...",
|
|
10155
|
+
refreshAction: "検索/列フィルタを保持して、この表だけ再読み込み",
|
|
10156
|
+
refreshActionWithFilters: (count) => `有効なフィルタ ${count} 件を保持して、この表だけ再読み込み`,
|
|
10157
|
+
refreshResultChanged: (delta, total) => {
|
|
10158
|
+
const abs = Math.abs(delta).toLocaleString();
|
|
10159
|
+
const sign = delta > 0 ? "+" : "-";
|
|
10160
|
+
return `行数 ${sign}${abs} (現在 ${total})`;
|
|
10161
|
+
},
|
|
10162
|
+
refreshResultUnchanged: (total) => `行数変化なし (${total})`,
|
|
9971
10163
|
exportAction: "エクスポート",
|
|
9972
10164
|
foreignKeyHint: "外部キー: クリックして関連データを表示",
|
|
9973
10165
|
relatedEmpty: "参照先に該当する行がありません",
|
|
10166
|
+
filteredEmptyTitle: (count) => `フィルタ ${count} 件に一致する行がありません`,
|
|
10167
|
+
filteredEmptyHint: "表は読み込めていますが、現在の検索/列フィルタですべての行が隠れています。",
|
|
10168
|
+
filteredEmptyAction: "フィルタ解除",
|
|
9974
10169
|
statusRows: (n2) => `${n2} 行`,
|
|
9975
10170
|
statusSort: (column, dir) => `並び替え: ${column} ${dir}`,
|
|
9976
|
-
statusFilters: (n2) => `フィルタ ${n2}
|
|
10171
|
+
statusFilters: (n2) => `フィルタ ${n2} 件`,
|
|
10172
|
+
statusRefreshing: (filters) => filters > 0 ? `フィルタ ${filters} 件を保持して再読み込み中…` : "この表を再読み込み中…"
|
|
9977
10173
|
},
|
|
9978
10174
|
edit: {
|
|
9979
10175
|
editMode: "編集",
|
|
@@ -9997,6 +10193,9 @@ ${frontmatter.yaml}
|
|
|
9997
10193
|
indexes: "インデックス",
|
|
9998
10194
|
triggers: "トリガー",
|
|
9999
10195
|
ddl: "DDL",
|
|
10196
|
+
refreshLabel: "スキーマを更新",
|
|
10197
|
+
refreshAction: "この表のスキーマを再読み込み",
|
|
10198
|
+
refreshingLabel: "更新中...",
|
|
10000
10199
|
copyDdl: "DDL をコピー",
|
|
10001
10200
|
copied: "コピーしました",
|
|
10002
10201
|
colName: "カラム",
|
|
@@ -10034,8 +10233,10 @@ ${frontmatter.yaml}
|
|
|
10034
10233
|
statusExplain: (ms) => `Explain (${ms}ms)`
|
|
10035
10234
|
},
|
|
10036
10235
|
history: {
|
|
10037
|
-
refresh: "
|
|
10038
|
-
refreshTitle: "
|
|
10236
|
+
refresh: "クエリ履歴を更新",
|
|
10237
|
+
refreshTitle: "クエリ履歴を再読み込み",
|
|
10238
|
+
refreshResultAdded: (count) => `+${count} 件`,
|
|
10239
|
+
refreshResultUnchanged: "新しいクエリはありません",
|
|
10039
10240
|
clearAll: "すべて削除",
|
|
10040
10241
|
clearTitle: "クエリ履歴をすべて削除",
|
|
10041
10242
|
selectPlaceholder: "クエリを選択すると詳細が表示されます",
|
|
@@ -10046,6 +10247,10 @@ ${frontmatter.yaml}
|
|
|
10046
10247
|
delete: "削除",
|
|
10047
10248
|
confirmDelete: "削除を確認",
|
|
10048
10249
|
confirmClear: "全削除を確認",
|
|
10250
|
+
executorAi: "AI",
|
|
10251
|
+
executorUser: "ユーザー",
|
|
10252
|
+
rowsLabel: (rows, truncated) => `${rows}${truncated ? "+" : ""} 行`,
|
|
10253
|
+
elapsedLabel: (ms) => `${ms}ms`,
|
|
10049
10254
|
truncatedRows: (saved, total) => `全 ${total} 行中 ${saved} 行を表示`
|
|
10050
10255
|
},
|
|
10051
10256
|
sessionLog: {
|
|
@@ -11861,16 +12066,22 @@ ${frontmatter.yaml}
|
|
|
11861
12066
|
const toolbar = document.createElement("div");
|
|
11862
12067
|
toolbar.className = "db-query-history-toolbar";
|
|
11863
12068
|
const refreshBtn = document.createElement("button");
|
|
11864
|
-
refreshBtn.className = "db-query-history-action";
|
|
12069
|
+
refreshBtn.className = "db-query-history-action db-query-history-refresh";
|
|
11865
12070
|
refreshBtn.type = "button";
|
|
11866
|
-
refreshBtn.
|
|
11867
|
-
|
|
12071
|
+
refreshBtn.innerHTML = iconSvg("octicon-sync", SYNC_16_PATH);
|
|
12072
|
+
const refreshLabel = document.createElement("span");
|
|
12073
|
+
refreshLabel.className = "db-query-history-action-label";
|
|
12074
|
+
refreshBtn.appendChild(refreshLabel);
|
|
12075
|
+
const refreshResult = document.createElement("span");
|
|
12076
|
+
refreshResult.className = "db-refresh-result db-query-history-refresh-result";
|
|
12077
|
+
refreshResult.setAttribute("aria-live", "polite");
|
|
12078
|
+
refreshResult.hidden = true;
|
|
11868
12079
|
const clearBtn = document.createElement("button");
|
|
11869
12080
|
clearBtn.className = "db-query-history-action db-query-history-danger";
|
|
11870
12081
|
clearBtn.type = "button";
|
|
11871
12082
|
clearBtn.textContent = text2().history.clearAll;
|
|
11872
12083
|
clearBtn.title = text2().history.clearTitle;
|
|
11873
|
-
toolbar.append(refreshBtn, clearBtn);
|
|
12084
|
+
toolbar.append(refreshBtn, refreshResult, clearBtn);
|
|
11874
12085
|
const body = document.createElement("div");
|
|
11875
12086
|
body.className = "db-query-history-body-split";
|
|
11876
12087
|
const listCol = document.createElement("div");
|
|
@@ -11894,6 +12105,50 @@ ${frontmatter.yaml}
|
|
|
11894
12105
|
let inFlightRefresh = null;
|
|
11895
12106
|
const entryRowsById = new Map;
|
|
11896
12107
|
let selectedEntryRow = null;
|
|
12108
|
+
let refreshResultState = { type: "none" };
|
|
12109
|
+
function syncRefreshButtonLabel() {
|
|
12110
|
+
refreshLabel.textContent = text2().history.refresh;
|
|
12111
|
+
refreshBtn.title = text2().history.refreshTitle;
|
|
12112
|
+
refreshBtn.setAttribute("aria-label", text2().history.refreshTitle);
|
|
12113
|
+
}
|
|
12114
|
+
function setRefreshBusy(isBusy) {
|
|
12115
|
+
refreshBtn.disabled = isBusy;
|
|
12116
|
+
refreshBtn.classList.toggle("spinning", isBusy);
|
|
12117
|
+
refreshBtn.setAttribute("aria-busy", isBusy ? "true" : "false");
|
|
12118
|
+
}
|
|
12119
|
+
function refreshResultText() {
|
|
12120
|
+
switch (refreshResultState.type) {
|
|
12121
|
+
case "none":
|
|
12122
|
+
return "";
|
|
12123
|
+
case "added":
|
|
12124
|
+
return text2().history.refreshResultAdded(refreshResultState.count);
|
|
12125
|
+
case "unchanged":
|
|
12126
|
+
return text2().history.refreshResultUnchanged;
|
|
12127
|
+
default: {
|
|
12128
|
+
const exhaustive = refreshResultState;
|
|
12129
|
+
return exhaustive;
|
|
12130
|
+
}
|
|
12131
|
+
}
|
|
12132
|
+
}
|
|
12133
|
+
function syncRefreshResult() {
|
|
12134
|
+
const message = refreshResultText();
|
|
12135
|
+
refreshResult.textContent = message;
|
|
12136
|
+
refreshResult.hidden = message.length === 0;
|
|
12137
|
+
refreshResult.classList.toggle("changed", refreshResultState.type === "added");
|
|
12138
|
+
}
|
|
12139
|
+
function clearRefreshResult() {
|
|
12140
|
+
refreshResultState = { type: "none" };
|
|
12141
|
+
syncRefreshResult();
|
|
12142
|
+
}
|
|
12143
|
+
function setRefreshResult(previousEntries, nextEntries) {
|
|
12144
|
+
const previousIds = new Set(previousEntries.map((entry) => entry.id));
|
|
12145
|
+
const added = nextEntries.filter((entry) => !previousIds.has(entry.id)).length;
|
|
12146
|
+
refreshResultState = added > 0 ? { type: "added", count: added } : { type: "unchanged" };
|
|
12147
|
+
syncRefreshResult();
|
|
12148
|
+
}
|
|
12149
|
+
syncRefreshButtonLabel();
|
|
12150
|
+
setRefreshBusy(false);
|
|
12151
|
+
syncRefreshResult();
|
|
11897
12152
|
function currentRefreshParams() {
|
|
11898
12153
|
const dbId = callbacks.getDbId();
|
|
11899
12154
|
const schema = callbacks.getSchema();
|
|
@@ -11930,6 +12185,10 @@ ${frontmatter.yaml}
|
|
|
11930
12185
|
if (!options.force && refreshKey === lastRefreshKey && now - lastRefreshAt < 1000) {
|
|
11931
12186
|
return;
|
|
11932
12187
|
}
|
|
12188
|
+
const previousEntries = options.announceResult ? [...entries] : null;
|
|
12189
|
+
if (options.announceResult)
|
|
12190
|
+
clearRefreshResult();
|
|
12191
|
+
setRefreshBusy(true);
|
|
11933
12192
|
const promise = (async () => {
|
|
11934
12193
|
const res = await fetch(`/_db/history${params}`);
|
|
11935
12194
|
if (!res.ok)
|
|
@@ -11938,6 +12197,8 @@ ${frontmatter.yaml}
|
|
|
11938
12197
|
if (currentRefreshParams().key !== refreshKey)
|
|
11939
12198
|
return;
|
|
11940
12199
|
entries = state.entries;
|
|
12200
|
+
if (previousEntries)
|
|
12201
|
+
setRefreshResult(previousEntries, entries);
|
|
11941
12202
|
lastRefreshKey = refreshKey;
|
|
11942
12203
|
lastRefreshAt = Date.now();
|
|
11943
12204
|
if (selectedEntryId && !entries.some((entry) => entry.id === selectedEntryId)) {
|
|
@@ -11949,8 +12210,10 @@ ${frontmatter.yaml}
|
|
|
11949
12210
|
try {
|
|
11950
12211
|
await promise;
|
|
11951
12212
|
} finally {
|
|
11952
|
-
if (inFlightRefresh?.promise === promise)
|
|
12213
|
+
if (inFlightRefresh?.promise === promise) {
|
|
11953
12214
|
inFlightRefresh = null;
|
|
12215
|
+
setRefreshBusy(false);
|
|
12216
|
+
}
|
|
11954
12217
|
}
|
|
11955
12218
|
}
|
|
11956
12219
|
function render() {
|
|
@@ -11987,6 +12250,7 @@ ${frontmatter.yaml}
|
|
|
11987
12250
|
}
|
|
11988
12251
|
function renderDetail(entry) {
|
|
11989
12252
|
detailCol.innerHTML = "";
|
|
12253
|
+
const meta = renderEntryMeta(entry, "detail");
|
|
11990
12254
|
const actions = document.createElement("div");
|
|
11991
12255
|
actions.className = "db-query-history-detail-actions";
|
|
11992
12256
|
const useBtn = document.createElement("button");
|
|
@@ -12021,7 +12285,7 @@ ${frontmatter.yaml}
|
|
|
12021
12285
|
const sqlBlock = document.createElement("pre");
|
|
12022
12286
|
sqlBlock.className = "db-query-history-sql";
|
|
12023
12287
|
sqlBlock.textContent = entry.sql;
|
|
12024
|
-
detailCol.append(actions, sqlBlock);
|
|
12288
|
+
detailCol.append(meta, actions, sqlBlock);
|
|
12025
12289
|
if (entry.body) {
|
|
12026
12290
|
const bodyBlock = document.createElement("div");
|
|
12027
12291
|
bodyBlock.className = "db-query-history-body";
|
|
@@ -12047,26 +12311,30 @@ ${frontmatter.yaml}
|
|
|
12047
12311
|
}
|
|
12048
12312
|
item.dataset.id = entry.id;
|
|
12049
12313
|
entryRowsById.set(entry.id, item);
|
|
12314
|
+
const meta = renderEntryMeta(entry, "entry");
|
|
12315
|
+
const title = document.createElement("div");
|
|
12316
|
+
title.className = "db-query-history-entry-title";
|
|
12317
|
+
title.textContent = entry.title || (entry.sql.length > 80 ? `${entry.sql.slice(0, 80)}...` : entry.sql);
|
|
12318
|
+
item.append(meta, title);
|
|
12319
|
+
item.addEventListener("click", () => selectEntry(entry));
|
|
12320
|
+
return item;
|
|
12321
|
+
}
|
|
12322
|
+
function renderEntryMeta(entry, mode) {
|
|
12050
12323
|
const meta = document.createElement("div");
|
|
12051
|
-
meta.className = "db-query-history-entry-meta";
|
|
12324
|
+
meta.className = mode === "detail" ? "db-query-history-detail-meta" : "db-query-history-entry-meta";
|
|
12052
12325
|
const byIcon = document.createElement("span");
|
|
12053
12326
|
byIcon.className = "db-query-history-by";
|
|
12054
|
-
|
|
12327
|
+
const executor = entry.executedBy === "ai" ? text2().history.executorAi : text2().history.executorUser;
|
|
12328
|
+
byIcon.textContent = mode === "detail" ? executor : `[${executor}]`;
|
|
12055
12329
|
const time = document.createElement("span");
|
|
12056
12330
|
time.className = "db-query-history-time";
|
|
12057
12331
|
time.textContent = formatTime(entry.executedAt);
|
|
12058
12332
|
time.title = entry.executedAt;
|
|
12059
12333
|
const stats = document.createElement("span");
|
|
12060
12334
|
stats.className = "db-query-history-stats";
|
|
12061
|
-
|
|
12062
|
-
stats.textContent = `${entry.rowCount}${truncMark} rows, ${entry.elapsedMs}ms`;
|
|
12335
|
+
stats.textContent = `${text2().history.rowsLabel(entry.rowCount, entry.truncated)}, ${text2().history.elapsedLabel(entry.elapsedMs)}`;
|
|
12063
12336
|
meta.append(byIcon, time, stats);
|
|
12064
|
-
|
|
12065
|
-
title.className = "db-query-history-entry-title";
|
|
12066
|
-
title.textContent = entry.title || (entry.sql.length > 80 ? `${entry.sql.slice(0, 80)}...` : entry.sql);
|
|
12067
|
-
item.append(meta, title);
|
|
12068
|
-
item.addEventListener("click", () => selectEntry(entry));
|
|
12069
|
-
return item;
|
|
12337
|
+
return meta;
|
|
12070
12338
|
}
|
|
12071
12339
|
function renderPreviewTable(entry) {
|
|
12072
12340
|
const wrapper = document.createElement("div");
|
|
@@ -12175,17 +12443,19 @@ ${frontmatter.yaml}
|
|
|
12175
12443
|
body: JSON.stringify(dbId ? { db: dbId, ...schema ? { schema } : {} } : {})
|
|
12176
12444
|
});
|
|
12177
12445
|
entries = [];
|
|
12446
|
+
clearRefreshResult();
|
|
12178
12447
|
render();
|
|
12179
12448
|
} catch {}
|
|
12180
12449
|
});
|
|
12181
12450
|
refreshBtn.addEventListener("click", () => {
|
|
12182
|
-
refresh({ force: true });
|
|
12451
|
+
refresh({ force: true, announceResult: true });
|
|
12183
12452
|
});
|
|
12184
12453
|
function clear() {
|
|
12185
12454
|
entries = [];
|
|
12186
12455
|
expandedIds.clear();
|
|
12187
12456
|
lastRefreshKey = null;
|
|
12188
12457
|
lastRefreshAt = 0;
|
|
12458
|
+
clearRefreshResult();
|
|
12189
12459
|
if (clearConfirmTimer) {
|
|
12190
12460
|
clearTimeout(clearConfirmTimer);
|
|
12191
12461
|
clearConfirmTimer = null;
|
|
@@ -12196,8 +12466,8 @@ ${frontmatter.yaml}
|
|
|
12196
12466
|
render();
|
|
12197
12467
|
}
|
|
12198
12468
|
function localize() {
|
|
12199
|
-
|
|
12200
|
-
|
|
12469
|
+
syncRefreshButtonLabel();
|
|
12470
|
+
syncRefreshResult();
|
|
12201
12471
|
if (clearBtn.dataset.confirm !== "1") {
|
|
12202
12472
|
clearBtn.textContent = text2().history.clearAll;
|
|
12203
12473
|
}
|
|
@@ -14261,7 +14531,25 @@ ${frontmatter.yaml}
|
|
|
14261
14531
|
const el = document.createElement("div");
|
|
14262
14532
|
el.className = "db-schema-view";
|
|
14263
14533
|
el.hidden = true;
|
|
14534
|
+
let refreshBusy = false;
|
|
14535
|
+
let refreshBtn = null;
|
|
14536
|
+
let refreshLabel = null;
|
|
14264
14537
|
let lastArgs = null;
|
|
14538
|
+
function syncRefreshButton() {
|
|
14539
|
+
if (!refreshBtn || !refreshLabel)
|
|
14540
|
+
return;
|
|
14541
|
+
const t2 = text2().schema;
|
|
14542
|
+
refreshBtn.title = t2.refreshAction;
|
|
14543
|
+
refreshBtn.setAttribute("aria-label", t2.refreshAction);
|
|
14544
|
+
refreshBtn.setAttribute("aria-busy", refreshBusy ? "true" : "false");
|
|
14545
|
+
refreshBtn.disabled = refreshBusy;
|
|
14546
|
+
refreshBtn.classList.toggle("spinning", refreshBusy);
|
|
14547
|
+
refreshLabel.textContent = refreshBusy ? t2.refreshingLabel : t2.refreshLabel;
|
|
14548
|
+
}
|
|
14549
|
+
function setRefreshBusy(busy) {
|
|
14550
|
+
refreshBusy = busy;
|
|
14551
|
+
syncRefreshButton();
|
|
14552
|
+
}
|
|
14265
14553
|
function render(table2, columns, indexes, extra) {
|
|
14266
14554
|
lastArgs = { table: table2, columns, indexes, extra };
|
|
14267
14555
|
const t2 = text2().schema;
|
|
@@ -14269,7 +14557,29 @@ ${frontmatter.yaml}
|
|
|
14269
14557
|
el.innerHTML = "";
|
|
14270
14558
|
const header = document.createElement("div");
|
|
14271
14559
|
header.className = "db-schema-header";
|
|
14272
|
-
|
|
14560
|
+
const headerTitle = document.createElement("span");
|
|
14561
|
+
headerTitle.className = "db-schema-header-title";
|
|
14562
|
+
headerTitle.textContent = `Schema: ${table2}`;
|
|
14563
|
+
header.appendChild(headerTitle);
|
|
14564
|
+
if (deps.onRefresh) {
|
|
14565
|
+
refreshBtn = document.createElement("button");
|
|
14566
|
+
refreshBtn.type = "button";
|
|
14567
|
+
refreshBtn.className = "db-btn db-btn-icon db-grid-refresh db-schema-refresh";
|
|
14568
|
+
refreshBtn.innerHTML = iconSvg("octicon-sync", SYNC_16_PATH);
|
|
14569
|
+
refreshLabel = document.createElement("span");
|
|
14570
|
+
refreshLabel.className = "db-grid-refresh-label";
|
|
14571
|
+
refreshBtn.appendChild(refreshLabel);
|
|
14572
|
+
refreshBtn.addEventListener("click", () => {
|
|
14573
|
+
if (refreshBusy)
|
|
14574
|
+
return;
|
|
14575
|
+
deps.onRefresh?.();
|
|
14576
|
+
});
|
|
14577
|
+
header.appendChild(refreshBtn);
|
|
14578
|
+
syncRefreshButton();
|
|
14579
|
+
} else {
|
|
14580
|
+
refreshBtn = null;
|
|
14581
|
+
refreshLabel = null;
|
|
14582
|
+
}
|
|
14273
14583
|
el.appendChild(header);
|
|
14274
14584
|
const colSectionHeader = document.createElement("div");
|
|
14275
14585
|
colSectionHeader.className = "db-schema-section-header";
|
|
@@ -14432,13 +14742,16 @@ ${frontmatter.yaml}
|
|
|
14432
14742
|
el.hidden = true;
|
|
14433
14743
|
el.innerHTML = "";
|
|
14434
14744
|
lastArgs = null;
|
|
14745
|
+
refreshBtn = null;
|
|
14746
|
+
refreshLabel = null;
|
|
14747
|
+
refreshBusy = false;
|
|
14435
14748
|
}
|
|
14436
14749
|
function localize() {
|
|
14437
14750
|
if (!lastArgs || el.hidden)
|
|
14438
14751
|
return;
|
|
14439
14752
|
render(lastArgs.table, lastArgs.columns, lastArgs.indexes, lastArgs.extra);
|
|
14440
14753
|
}
|
|
14441
|
-
return { el, render, clear, localize };
|
|
14754
|
+
return { el, render, clear, localize, setRefreshBusy };
|
|
14442
14755
|
}
|
|
14443
14756
|
|
|
14444
14757
|
// web-src/views/database/session-log.ts
|
|
@@ -15866,7 +16179,8 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
15866
16179
|
filterBar.className = "db-grid-filter-bar";
|
|
15867
16180
|
const filterIcon = document.createElement("span");
|
|
15868
16181
|
filterIcon.className = "db-grid-filter-icon";
|
|
15869
|
-
filterIcon.
|
|
16182
|
+
filterIcon.setAttribute("aria-hidden", "true");
|
|
16183
|
+
filterIcon.innerHTML = iconSvg("octicon-search", SEARCH_16_PATH);
|
|
15870
16184
|
const filterInput = document.createElement("input");
|
|
15871
16185
|
filterInput.type = "search";
|
|
15872
16186
|
filterInput.className = "db-grid-filter-input";
|
|
@@ -15874,9 +16188,24 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
15874
16188
|
filterInput.autocomplete = "off";
|
|
15875
16189
|
const filterClear = document.createElement("button");
|
|
15876
16190
|
filterClear.type = "button";
|
|
15877
|
-
filterClear.className = "db-btn db-btn-
|
|
15878
|
-
filterClear.textContent =
|
|
16191
|
+
filterClear.className = "db-btn db-btn-sm db-grid-filter-clear";
|
|
16192
|
+
filterClear.textContent = text2().grid.clearFiltersLabel;
|
|
15879
16193
|
filterClear.hidden = true;
|
|
16194
|
+
const refreshBtn = document.createElement("button");
|
|
16195
|
+
refreshBtn.type = "button";
|
|
16196
|
+
refreshBtn.className = "db-btn db-btn-icon db-grid-refresh";
|
|
16197
|
+
refreshBtn.title = text2().grid.refreshAction;
|
|
16198
|
+
refreshBtn.setAttribute("aria-label", text2().grid.refreshAction);
|
|
16199
|
+
refreshBtn.setAttribute("aria-busy", "false");
|
|
16200
|
+
refreshBtn.innerHTML = iconSvg("octicon-sync", SYNC_16_PATH);
|
|
16201
|
+
const refreshLabel = document.createElement("span");
|
|
16202
|
+
refreshLabel.className = "db-grid-refresh-label";
|
|
16203
|
+
refreshLabel.textContent = text2().grid.refreshLabel;
|
|
16204
|
+
refreshBtn.appendChild(refreshLabel);
|
|
16205
|
+
const refreshResult = document.createElement("span");
|
|
16206
|
+
refreshResult.className = "db-refresh-result db-grid-refresh-result";
|
|
16207
|
+
refreshResult.setAttribute("aria-live", "polite");
|
|
16208
|
+
refreshResult.hidden = true;
|
|
15880
16209
|
const exportWrap = document.createElement("div");
|
|
15881
16210
|
exportWrap.className = "db-grid-export";
|
|
15882
16211
|
const exportBtn = document.createElement("button");
|
|
@@ -15884,7 +16213,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
15884
16213
|
exportBtn.className = "db-btn db-btn-icon db-grid-export-toggle";
|
|
15885
16214
|
exportBtn.title = text2().grid.exportAction;
|
|
15886
16215
|
exportBtn.setAttribute("aria-label", text2().grid.exportAction);
|
|
15887
|
-
exportBtn.
|
|
16216
|
+
exportBtn.innerHTML = iconSvg("octicon-download", DOWNLOAD_16_PATHS);
|
|
15888
16217
|
const exportMenu = document.createElement("div");
|
|
15889
16218
|
exportMenu.className = "db-grid-export-menu";
|
|
15890
16219
|
exportMenu.hidden = true;
|
|
@@ -15944,7 +16273,10 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
15944
16273
|
const editStatus = document.createElement("span");
|
|
15945
16274
|
editStatus.className = "db-grid-edit-status";
|
|
15946
16275
|
editWrap.append(newRowBtn, commitBtn, discardBtn, editStatus);
|
|
15947
|
-
|
|
16276
|
+
const filterActions = document.createElement("div");
|
|
16277
|
+
filterActions.className = "db-grid-filter-actions";
|
|
16278
|
+
filterActions.append(refreshBtn, refreshResult, exportWrap);
|
|
16279
|
+
filterBar.append(filterIcon, filterInput, filterClear, editWrap, filterActions);
|
|
15948
16280
|
const headerWrap = document.createElement("div");
|
|
15949
16281
|
headerWrap.className = "db-grid-header-wrap";
|
|
15950
16282
|
const headerRow = document.createElement("div");
|
|
@@ -15961,6 +16293,31 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
15961
16293
|
spacer.className = "db-grid-spacer";
|
|
15962
16294
|
const body = document.createElement("div");
|
|
15963
16295
|
body.className = "db-grid-body";
|
|
16296
|
+
const filteredEmpty = document.createElement("div");
|
|
16297
|
+
filteredEmpty.className = "db-pane-empty";
|
|
16298
|
+
filteredEmpty.hidden = true;
|
|
16299
|
+
const filteredEmptyIcon = document.createElement("div");
|
|
16300
|
+
filteredEmptyIcon.className = "db-pane-empty-icon";
|
|
16301
|
+
filteredEmptyIcon.innerHTML = iconSvg("octicon-search", SEARCH_16_PATH);
|
|
16302
|
+
const filteredEmptyTitle = document.createElement("div");
|
|
16303
|
+
filteredEmptyTitle.className = "db-pane-empty-title";
|
|
16304
|
+
const filteredEmptyHint = document.createElement("div");
|
|
16305
|
+
filteredEmptyHint.className = "db-pane-empty-hint";
|
|
16306
|
+
const filteredEmptyActions = document.createElement("div");
|
|
16307
|
+
filteredEmptyActions.className = "db-pane-empty-actions";
|
|
16308
|
+
filteredEmptyActions.hidden = true;
|
|
16309
|
+
const filteredEmptyReloadAction = document.createElement("button");
|
|
16310
|
+
filteredEmptyReloadAction.type = "button";
|
|
16311
|
+
filteredEmptyReloadAction.className = "db-btn db-btn-primary db-btn-sm";
|
|
16312
|
+
filteredEmptyReloadAction.hidden = true;
|
|
16313
|
+
filteredEmptyReloadAction.disabled = true;
|
|
16314
|
+
const filteredEmptyAction = document.createElement("button");
|
|
16315
|
+
filteredEmptyAction.type = "button";
|
|
16316
|
+
filteredEmptyAction.className = "db-btn db-btn-sm";
|
|
16317
|
+
filteredEmptyAction.hidden = true;
|
|
16318
|
+
filteredEmptyAction.disabled = true;
|
|
16319
|
+
filteredEmptyActions.append(filteredEmptyReloadAction, filteredEmptyAction);
|
|
16320
|
+
filteredEmpty.append(filteredEmptyIcon, filteredEmptyTitle, filteredEmptyHint, filteredEmptyActions);
|
|
15964
16321
|
const detailPanel = document.createElement("div");
|
|
15965
16322
|
detailPanel.className = "db-grid-detail-panel";
|
|
15966
16323
|
detailPanel.hidden = true;
|
|
@@ -15968,7 +16325,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
15968
16325
|
detailResize.className = "db-grid-detail-resize";
|
|
15969
16326
|
detailResize.addEventListener("mousedown", startDetailResize);
|
|
15970
16327
|
detailPanel.appendChild(detailResize);
|
|
15971
|
-
viewport.append(spacer, body);
|
|
16328
|
+
viewport.append(spacer, body, filteredEmpty);
|
|
15972
16329
|
el.append(filterBar, headerWrap, filterRowWrap, viewport, detailPanel);
|
|
15973
16330
|
function panelMaxHeight() {
|
|
15974
16331
|
const containerH = el.clientHeight || window.innerHeight;
|
|
@@ -16046,6 +16403,8 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
16046
16403
|
let loadController = new AbortController;
|
|
16047
16404
|
let rafId = 0;
|
|
16048
16405
|
let statusEl = null;
|
|
16406
|
+
let isRefreshing = false;
|
|
16407
|
+
let refreshResultState = null;
|
|
16049
16408
|
let filterTimer = null;
|
|
16050
16409
|
let selectedRowIndex = -1;
|
|
16051
16410
|
let activeCellRowIndex = -1;
|
|
@@ -16140,19 +16499,109 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
16140
16499
|
syncContentWidth();
|
|
16141
16500
|
renderViewport();
|
|
16142
16501
|
}
|
|
16143
|
-
function
|
|
16502
|
+
function collectColumnFilters() {
|
|
16144
16503
|
const filters = [];
|
|
16145
16504
|
for (const [col, val] of columnFilters) {
|
|
16146
16505
|
if (val)
|
|
16147
16506
|
filters.push({ column: col, value: val });
|
|
16148
16507
|
}
|
|
16149
|
-
|
|
16508
|
+
return filters;
|
|
16509
|
+
}
|
|
16510
|
+
function collectFilters() {
|
|
16511
|
+
const filters = collectColumnFilters();
|
|
16512
|
+
if (globalSearchValue) {
|
|
16150
16513
|
for (const col of columnNames) {
|
|
16151
|
-
filters.
|
|
16514
|
+
if (!filters.some((filter) => filter.column === col && filter.value === globalSearchValue)) {
|
|
16515
|
+
filters.push({ column: col, value: globalSearchValue });
|
|
16516
|
+
}
|
|
16152
16517
|
}
|
|
16153
16518
|
}
|
|
16154
16519
|
return filters;
|
|
16155
16520
|
}
|
|
16521
|
+
function activeFilterCount() {
|
|
16522
|
+
return columnFilters.size + (globalSearchValue ? 1 : 0);
|
|
16523
|
+
}
|
|
16524
|
+
function syncRefreshButton() {
|
|
16525
|
+
const count = activeFilterCount();
|
|
16526
|
+
const t2 = text2().grid;
|
|
16527
|
+
refreshLabel.textContent = isRefreshing ? t2.refreshingLabel : count > 0 ? t2.refreshFilteredLabel : t2.refreshLabel;
|
|
16528
|
+
const action = count > 0 ? t2.refreshActionWithFilters(count) : t2.refreshAction;
|
|
16529
|
+
refreshBtn.classList.toggle("has-filters", count > 0);
|
|
16530
|
+
refreshBtn.title = action;
|
|
16531
|
+
refreshBtn.setAttribute("aria-label", action);
|
|
16532
|
+
refreshBtn.setAttribute("aria-busy", isRefreshing ? "true" : "false");
|
|
16533
|
+
}
|
|
16534
|
+
function syncRefreshResult() {
|
|
16535
|
+
const result = refreshResultState;
|
|
16536
|
+
refreshResult.hidden = !result;
|
|
16537
|
+
refreshResult.classList.toggle("changed", !!result && result.delta !== 0);
|
|
16538
|
+
if (!result) {
|
|
16539
|
+
refreshResult.textContent = "";
|
|
16540
|
+
return;
|
|
16541
|
+
}
|
|
16542
|
+
const t2 = text2().grid;
|
|
16543
|
+
const total = result.totalRows.toLocaleString();
|
|
16544
|
+
refreshResult.textContent = result.delta === 0 ? t2.refreshResultUnchanged(total) : t2.refreshResultChanged(result.delta, total);
|
|
16545
|
+
}
|
|
16546
|
+
function clearRefreshResult() {
|
|
16547
|
+
refreshResultState = null;
|
|
16548
|
+
syncRefreshResult();
|
|
16549
|
+
}
|
|
16550
|
+
function setRefreshResult(previousTotalRows, nextTotalRows) {
|
|
16551
|
+
refreshResultState = {
|
|
16552
|
+
delta: nextTotalRows - previousTotalRows,
|
|
16553
|
+
totalRows: nextTotalRows
|
|
16554
|
+
};
|
|
16555
|
+
syncRefreshResult();
|
|
16556
|
+
}
|
|
16557
|
+
function syncFilterClearButton() {
|
|
16558
|
+
const count = activeFilterCount();
|
|
16559
|
+
const t2 = text2().grid;
|
|
16560
|
+
filterClear.hidden = count === 0;
|
|
16561
|
+
filterClear.textContent = t2.clearFiltersLabel;
|
|
16562
|
+
const action = t2.clearFiltersAction(count);
|
|
16563
|
+
filterClear.title = action;
|
|
16564
|
+
filterClear.setAttribute("aria-label", action);
|
|
16565
|
+
}
|
|
16566
|
+
function syncFilteredEmptyState() {
|
|
16567
|
+
const count = activeFilterCount();
|
|
16568
|
+
const show = totalRows === 0 && count > 0;
|
|
16569
|
+
filteredEmpty.hidden = !show;
|
|
16570
|
+
filteredEmptyActions.hidden = !show;
|
|
16571
|
+
filteredEmptyReloadAction.hidden = !show;
|
|
16572
|
+
filteredEmptyReloadAction.disabled = !show || isRefreshing;
|
|
16573
|
+
filteredEmptyAction.hidden = !show;
|
|
16574
|
+
filteredEmptyAction.disabled = !show;
|
|
16575
|
+
if (!show)
|
|
16576
|
+
return;
|
|
16577
|
+
const t2 = text2().grid;
|
|
16578
|
+
const reloadAction = t2.refreshActionWithFilters(count);
|
|
16579
|
+
filteredEmptyTitle.textContent = t2.filteredEmptyTitle(count);
|
|
16580
|
+
filteredEmptyHint.textContent = t2.filteredEmptyHint;
|
|
16581
|
+
filteredEmptyReloadAction.textContent = isRefreshing ? t2.refreshingLabel : t2.refreshFilteredLabel;
|
|
16582
|
+
filteredEmptyReloadAction.title = reloadAction;
|
|
16583
|
+
filteredEmptyReloadAction.setAttribute("aria-label", reloadAction);
|
|
16584
|
+
filteredEmptyReloadAction.setAttribute("aria-busy", isRefreshing ? "true" : "false");
|
|
16585
|
+
filteredEmptyAction.textContent = t2.filteredEmptyAction;
|
|
16586
|
+
filteredEmptyAction.title = t2.clearFiltersAction(count);
|
|
16587
|
+
filteredEmptyAction.setAttribute("aria-label", t2.clearFiltersAction(count));
|
|
16588
|
+
}
|
|
16589
|
+
function clearAllFilters() {
|
|
16590
|
+
globalSearchValue = "";
|
|
16591
|
+
filterInput.value = "";
|
|
16592
|
+
columnFilters.clear();
|
|
16593
|
+
clearRefreshResult();
|
|
16594
|
+
filterRow.querySelectorAll(".db-grid-col-filter").forEach((input) => {
|
|
16595
|
+
input.value = "";
|
|
16596
|
+
});
|
|
16597
|
+
syncFilterClearButton();
|
|
16598
|
+
syncRefreshButton();
|
|
16599
|
+
syncFilteredEmptyState();
|
|
16600
|
+
}
|
|
16601
|
+
function clearFiltersAndReload() {
|
|
16602
|
+
clearAllFilters();
|
|
16603
|
+
invalidateData();
|
|
16604
|
+
}
|
|
16156
16605
|
function resetSelectionAndDetail() {
|
|
16157
16606
|
selectedRowIndex = -1;
|
|
16158
16607
|
detailPanel.hidden = true;
|
|
@@ -16169,11 +16618,60 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
16169
16618
|
function invalidateData() {
|
|
16170
16619
|
pageCache = new Map;
|
|
16171
16620
|
pendingPages = new Map;
|
|
16621
|
+
clearRefreshResult();
|
|
16172
16622
|
startNewLoadGeneration();
|
|
16173
16623
|
viewport.scrollTop = 0;
|
|
16174
16624
|
resetSelectionAndDetail();
|
|
16175
16625
|
return ensurePage(0);
|
|
16176
16626
|
}
|
|
16627
|
+
async function refreshCurrentTable() {
|
|
16628
|
+
if (!currentTable || refreshBtn.disabled)
|
|
16629
|
+
return;
|
|
16630
|
+
const refreshTable = currentTable;
|
|
16631
|
+
const previousTotalRows = totalRows;
|
|
16632
|
+
const refreshFilterKey = JSON.stringify(collectFilters());
|
|
16633
|
+
const scrollTop = viewport.scrollTop;
|
|
16634
|
+
const pageStart = Math.floor(scrollTop / ROW_HEIGHT / PAGE_SIZE) * PAGE_SIZE;
|
|
16635
|
+
refreshBtn.disabled = true;
|
|
16636
|
+
refreshBtn.classList.add("spinning");
|
|
16637
|
+
isRefreshing = true;
|
|
16638
|
+
clearRefreshResult();
|
|
16639
|
+
syncRefreshButton();
|
|
16640
|
+
syncFilteredEmptyState();
|
|
16641
|
+
updateStatus();
|
|
16642
|
+
if (filterTimer) {
|
|
16643
|
+
clearTimeout(filterTimer);
|
|
16644
|
+
filterTimer = null;
|
|
16645
|
+
}
|
|
16646
|
+
pageCache = new Map;
|
|
16647
|
+
pendingPages = new Map;
|
|
16648
|
+
startNewLoadGeneration();
|
|
16649
|
+
const refreshGeneration = loadGeneration;
|
|
16650
|
+
resetSelectionAndDetail();
|
|
16651
|
+
viewport.scrollTop = scrollTop;
|
|
16652
|
+
renderViewport();
|
|
16653
|
+
try {
|
|
16654
|
+
await ensurePage(pageStart);
|
|
16655
|
+
} finally {
|
|
16656
|
+
const endedInError = statusEl?.classList.contains("db-pane-error");
|
|
16657
|
+
isRefreshing = false;
|
|
16658
|
+
refreshBtn.classList.remove("spinning");
|
|
16659
|
+
refreshBtn.disabled = false;
|
|
16660
|
+
syncRefreshButton();
|
|
16661
|
+
syncFilteredEmptyState();
|
|
16662
|
+
if (!endedInError) {
|
|
16663
|
+
if (loadGeneration === refreshGeneration && JSON.stringify(collectFilters()) === refreshFilterKey) {
|
|
16664
|
+
setRefreshResult(previousTotalRows, totalRows);
|
|
16665
|
+
callbacks.onRefreshComplete?.({
|
|
16666
|
+
table: refreshTable,
|
|
16667
|
+
totalRows,
|
|
16668
|
+
filters: collectFilters()
|
|
16669
|
+
});
|
|
16670
|
+
}
|
|
16671
|
+
updateStatus();
|
|
16672
|
+
}
|
|
16673
|
+
}
|
|
16674
|
+
}
|
|
16177
16675
|
function clear() {
|
|
16178
16676
|
cleanupResize();
|
|
16179
16677
|
clearActiveCell();
|
|
@@ -16182,10 +16680,13 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
16182
16680
|
columnNames = [];
|
|
16183
16681
|
totalRows = 0;
|
|
16184
16682
|
sort = null;
|
|
16683
|
+
isRefreshing = false;
|
|
16185
16684
|
columnFilters.clear();
|
|
16186
16685
|
globalSearchValue = "";
|
|
16686
|
+
clearRefreshResult();
|
|
16187
16687
|
filterInput.value = "";
|
|
16188
|
-
|
|
16688
|
+
syncFilterClearButton();
|
|
16689
|
+
syncRefreshButton();
|
|
16189
16690
|
filterRow.innerHTML = "";
|
|
16190
16691
|
pageCache = new Map;
|
|
16191
16692
|
pendingPages = new Map;
|
|
@@ -16278,7 +16779,8 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
16278
16779
|
header.className = "db-related-header";
|
|
16279
16780
|
const title = document.createElement("span");
|
|
16280
16781
|
title.className = "db-related-title";
|
|
16281
|
-
title.
|
|
16782
|
+
title.setAttribute("aria-hidden", "true");
|
|
16783
|
+
title.innerHTML = iconSvg("octicon-link", LINK_16_PATH);
|
|
16282
16784
|
relatedCrumbEl = document.createElement("span");
|
|
16283
16785
|
relatedCrumbEl.className = "db-related-crumbs";
|
|
16284
16786
|
const copyBtn = document.createElement("button");
|
|
@@ -16582,7 +17084,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
16582
17084
|
cell.classList.add("db-grid-header-fk");
|
|
16583
17085
|
const fkIcon = document.createElement("span");
|
|
16584
17086
|
fkIcon.className = "db-grid-header-fk-icon";
|
|
16585
|
-
fkIcon.
|
|
17087
|
+
fkIcon.innerHTML = iconSvg("octicon-link", LINK_16_PATH);
|
|
16586
17088
|
fkIcon.title = text2().grid.foreignKeyHint;
|
|
16587
17089
|
label.appendChild(fkIcon);
|
|
16588
17090
|
}
|
|
@@ -16668,6 +17170,9 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
16668
17170
|
} else {
|
|
16669
17171
|
columnFilters.delete(col.name);
|
|
16670
17172
|
}
|
|
17173
|
+
clearRefreshResult();
|
|
17174
|
+
syncFilterClearButton();
|
|
17175
|
+
syncRefreshButton();
|
|
16671
17176
|
scheduleFilter();
|
|
16672
17177
|
});
|
|
16673
17178
|
input.addEventListener("keydown", (e2) => {
|
|
@@ -16676,6 +17181,9 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
16676
17181
|
if (e2.key === "Escape") {
|
|
16677
17182
|
input.value = "";
|
|
16678
17183
|
columnFilters.delete(col.name);
|
|
17184
|
+
clearRefreshResult();
|
|
17185
|
+
syncFilterClearButton();
|
|
17186
|
+
syncRefreshButton();
|
|
16679
17187
|
scheduleFilter();
|
|
16680
17188
|
}
|
|
16681
17189
|
});
|
|
@@ -16687,6 +17195,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
16687
17195
|
if (filterTimer)
|
|
16688
17196
|
clearTimeout(filterTimer);
|
|
16689
17197
|
filterTimer = setTimeout(() => {
|
|
17198
|
+
filterTimer = null;
|
|
16690
17199
|
invalidateData();
|
|
16691
17200
|
}, FILTER_DEBOUNCE_MS);
|
|
16692
17201
|
}
|
|
@@ -17065,6 +17574,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
17065
17574
|
for (let i2 = startRow;i2 < endRow; i2++) {
|
|
17066
17575
|
body.appendChild(i2 < totalRows ? buildDataRow(i2) : buildDraftRow(i2 - totalRows));
|
|
17067
17576
|
}
|
|
17577
|
+
syncFilteredEmptyState();
|
|
17068
17578
|
if (focusRestore) {
|
|
17069
17579
|
const next = body.querySelector(`.db-grid-cell-input[data-edit-row="${focusRestore.row}"][data-edit-col="${focusRestore.col}"]`);
|
|
17070
17580
|
if (next) {
|
|
@@ -17114,15 +17624,18 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
17114
17624
|
const parts = [t2.statusRows(totalRows.toLocaleString())];
|
|
17115
17625
|
if (sort)
|
|
17116
17626
|
parts.push(t2.statusSort(sort.column, sort.direction.toUpperCase()));
|
|
17117
|
-
const
|
|
17118
|
-
if (
|
|
17119
|
-
parts.push(t2.statusFilters(
|
|
17627
|
+
const filterCount = activeFilterCount();
|
|
17628
|
+
if (filterCount > 0)
|
|
17629
|
+
parts.push(t2.statusFilters(filterCount));
|
|
17630
|
+
if (isRefreshing)
|
|
17631
|
+
parts.push(t2.statusRefreshing(filterCount));
|
|
17120
17632
|
const textNode = statusEl.firstChild;
|
|
17121
17633
|
if (textNode && textNode.nodeType === Node.TEXT_NODE) {
|
|
17122
17634
|
textNode.textContent = `${parts.join(" | ")} `;
|
|
17123
17635
|
} else {
|
|
17124
17636
|
statusEl.insertBefore(document.createTextNode(`${parts.join(" | ")} `), statusEl.firstChild);
|
|
17125
17637
|
}
|
|
17638
|
+
syncRefreshResult();
|
|
17126
17639
|
}
|
|
17127
17640
|
function showError(message) {
|
|
17128
17641
|
clear();
|
|
@@ -17161,13 +17674,14 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
17161
17674
|
if (state.search !== undefined) {
|
|
17162
17675
|
globalSearchValue = state.search;
|
|
17163
17676
|
filterInput.value = state.search;
|
|
17164
|
-
filterClear.hidden = !globalSearchValue;
|
|
17165
17677
|
}
|
|
17166
17678
|
columnFilters.clear();
|
|
17167
17679
|
for (const filter of state.filters || []) {
|
|
17168
17680
|
if (filter.column && filter.value)
|
|
17169
17681
|
columnFilters.set(filter.column, filter.value);
|
|
17170
17682
|
}
|
|
17683
|
+
syncFilterClearButton();
|
|
17684
|
+
syncRefreshButton();
|
|
17171
17685
|
sort = state.sort || null;
|
|
17172
17686
|
const targetRowIndex = state.row && state.row > 0 ? state.row - 1 : -1;
|
|
17173
17687
|
renderHeader();
|
|
@@ -17180,7 +17694,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
17180
17694
|
}
|
|
17181
17695
|
}
|
|
17182
17696
|
function getState() {
|
|
17183
|
-
const filters =
|
|
17697
|
+
const filters = collectColumnFilters();
|
|
17184
17698
|
return {
|
|
17185
17699
|
...globalSearchValue ? { search: globalSearchValue } : {},
|
|
17186
17700
|
...filters.length ? { filters } : {},
|
|
@@ -17190,7 +17704,9 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
17190
17704
|
}
|
|
17191
17705
|
filterInput.addEventListener("input", () => {
|
|
17192
17706
|
globalSearchValue = filterInput.value.trim();
|
|
17193
|
-
|
|
17707
|
+
clearRefreshResult();
|
|
17708
|
+
syncFilterClearButton();
|
|
17709
|
+
syncRefreshButton();
|
|
17194
17710
|
scheduleFilter();
|
|
17195
17711
|
});
|
|
17196
17712
|
filterInput.addEventListener("keydown", (e2) => {
|
|
@@ -17199,15 +17715,24 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
17199
17715
|
if (e2.key === "Escape") {
|
|
17200
17716
|
filterInput.value = "";
|
|
17201
17717
|
globalSearchValue = "";
|
|
17202
|
-
|
|
17718
|
+
clearRefreshResult();
|
|
17719
|
+
syncFilterClearButton();
|
|
17720
|
+
syncRefreshButton();
|
|
17203
17721
|
scheduleFilter();
|
|
17204
17722
|
}
|
|
17205
17723
|
});
|
|
17206
17724
|
filterClear.addEventListener("click", () => {
|
|
17207
|
-
|
|
17208
|
-
|
|
17209
|
-
|
|
17210
|
-
|
|
17725
|
+
clearFiltersAndReload();
|
|
17726
|
+
});
|
|
17727
|
+
filteredEmptyAction.addEventListener("click", () => {
|
|
17728
|
+
clearFiltersAndReload();
|
|
17729
|
+
filterInput.focus?.();
|
|
17730
|
+
});
|
|
17731
|
+
filteredEmptyReloadAction.addEventListener("click", () => {
|
|
17732
|
+
refreshCurrentTable();
|
|
17733
|
+
});
|
|
17734
|
+
refreshBtn.addEventListener("click", () => {
|
|
17735
|
+
refreshCurrentTable();
|
|
17211
17736
|
});
|
|
17212
17737
|
const onViewportScroll = () => {
|
|
17213
17738
|
headerWrap.scrollLeft = viewport.scrollLeft;
|
|
@@ -17236,6 +17761,10 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
17236
17761
|
function localize() {
|
|
17237
17762
|
const t2 = text2();
|
|
17238
17763
|
filterInput.placeholder = t2.grid.searchPlaceholder;
|
|
17764
|
+
syncFilterClearButton();
|
|
17765
|
+
syncRefreshButton();
|
|
17766
|
+
syncRefreshResult();
|
|
17767
|
+
syncFilteredEmptyState();
|
|
17239
17768
|
exportBtn.title = t2.grid.exportAction;
|
|
17240
17769
|
exportBtn.setAttribute("aria-label", t2.grid.exportAction);
|
|
17241
17770
|
newRowBtn.textContent = t2.edit.newRow;
|
|
@@ -17517,6 +18046,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
17517
18046
|
return {
|
|
17518
18047
|
el,
|
|
17519
18048
|
load,
|
|
18049
|
+
refresh: refreshCurrentTable,
|
|
17520
18050
|
showError,
|
|
17521
18051
|
applyState,
|
|
17522
18052
|
getState,
|
|
@@ -17575,7 +18105,14 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
17575
18105
|
filterInput.className = "db-table-filter";
|
|
17576
18106
|
filterInput.type = "text";
|
|
17577
18107
|
filterInput.placeholder = "Filter tables...";
|
|
17578
|
-
|
|
18108
|
+
const filterClear = document.createElement("button");
|
|
18109
|
+
filterClear.className = "db-table-filter-clear";
|
|
18110
|
+
filterClear.type = "button";
|
|
18111
|
+
filterClear.title = "Clear table filter";
|
|
18112
|
+
filterClear.setAttribute("aria-label", "Clear table filter");
|
|
18113
|
+
filterClear.innerHTML = iconSvg("octicon-x", X_16_PATH);
|
|
18114
|
+
filterClear.hidden = true;
|
|
18115
|
+
filterWrap.append(filterInput, filterClear);
|
|
17579
18116
|
const el = document.createElement("div");
|
|
17580
18117
|
el.className = "db-table-list";
|
|
17581
18118
|
wrapper.append(filterWrap, el);
|
|
@@ -17735,13 +18272,37 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
17735
18272
|
}
|
|
17736
18273
|
}
|
|
17737
18274
|
}
|
|
18275
|
+
function syncFilterClearButton() {
|
|
18276
|
+
filterClear.hidden = filterInput.value.length === 0;
|
|
18277
|
+
}
|
|
18278
|
+
function clearFilter() {
|
|
18279
|
+
if (!filterInput.value)
|
|
18280
|
+
return;
|
|
18281
|
+
filterInput.value = "";
|
|
18282
|
+
renderFiltered(allTables, "");
|
|
18283
|
+
filterInput.focus();
|
|
18284
|
+
}
|
|
17738
18285
|
function renderFiltered(tables, filter) {
|
|
17739
18286
|
el.innerHTML = "";
|
|
18287
|
+
syncFilterClearButton();
|
|
17740
18288
|
const filtered = filter ? tables.filter((t2) => t2.name.toLowerCase().includes(filter.toLowerCase())) : tables;
|
|
17741
18289
|
if (filtered.length === 0) {
|
|
17742
18290
|
const empty = document.createElement("div");
|
|
17743
18291
|
empty.className = "db-table-list-empty";
|
|
17744
18292
|
empty.textContent = filter ? "No matching tables" : "No tables found";
|
|
18293
|
+
if (filter) {
|
|
18294
|
+
const actions = document.createElement("div");
|
|
18295
|
+
actions.className = "db-pane-empty-actions db-table-list-empty-actions";
|
|
18296
|
+
const clear = document.createElement("button");
|
|
18297
|
+
clear.type = "button";
|
|
18298
|
+
clear.className = "db-btn db-btn-sm";
|
|
18299
|
+
clear.textContent = "Clear filter";
|
|
18300
|
+
clear.title = "Clear table filter";
|
|
18301
|
+
clear.setAttribute("aria-label", "Clear table filter");
|
|
18302
|
+
clear.addEventListener("click", clearFilter);
|
|
18303
|
+
actions.appendChild(clear);
|
|
18304
|
+
empty.appendChild(actions);
|
|
18305
|
+
}
|
|
17745
18306
|
el.appendChild(empty);
|
|
17746
18307
|
return;
|
|
17747
18308
|
}
|
|
@@ -17811,23 +18372,37 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
17811
18372
|
filterInput.value = "";
|
|
17812
18373
|
renderFiltered(tables, "");
|
|
17813
18374
|
}
|
|
17814
|
-
|
|
18375
|
+
function handleFilterInput() {
|
|
17815
18376
|
renderFiltered(allTables, filterInput.value);
|
|
17816
|
-
}
|
|
18377
|
+
}
|
|
18378
|
+
filterInput.addEventListener("input", handleFilterInput);
|
|
18379
|
+
filterClear.addEventListener("click", clearFilter);
|
|
17817
18380
|
function setActive(table2) {
|
|
17818
18381
|
activeTable = table2;
|
|
17819
18382
|
el.querySelectorAll(".db-table-item").forEach((item) => {
|
|
17820
18383
|
item.classList.toggle("active", item.dataset.table === table2);
|
|
17821
18384
|
});
|
|
17822
18385
|
}
|
|
18386
|
+
function updateRowCount(table2, rowCount) {
|
|
18387
|
+
allTables = allTables.map((entry) => entry.name === table2 ? { ...entry, rowCount } : entry);
|
|
18388
|
+
for (const node of el.querySelectorAll(".db-table-node")) {
|
|
18389
|
+
if (node.dataset.table !== table2)
|
|
18390
|
+
continue;
|
|
18391
|
+
const count = node.querySelector(".db-table-count");
|
|
18392
|
+
if (count)
|
|
18393
|
+
count.textContent = rowCount != null ? formatRowCount(rowCount) : "";
|
|
18394
|
+
}
|
|
18395
|
+
}
|
|
17823
18396
|
function dispose() {
|
|
17824
18397
|
closeContextMenu();
|
|
17825
18398
|
allTables = [];
|
|
17826
18399
|
expandedTables.clear();
|
|
17827
18400
|
columnCache.clear();
|
|
17828
18401
|
activeTable = null;
|
|
18402
|
+
filterInput.removeEventListener("input", handleFilterInput);
|
|
18403
|
+
filterClear.removeEventListener("click", clearFilter);
|
|
17829
18404
|
}
|
|
17830
|
-
return { el: wrapper, render, setActive, dispose };
|
|
18405
|
+
return { el: wrapper, render, setActive, updateRowCount, dispose };
|
|
17831
18406
|
}
|
|
17832
18407
|
function formatRowCount(n2) {
|
|
17833
18408
|
if (n2 >= 1e6)
|
|
@@ -17981,11 +18556,14 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
17981
18556
|
return value;
|
|
17982
18557
|
}
|
|
17983
18558
|
let lastFiles = [];
|
|
18559
|
+
let noDatastoresAvailable = false;
|
|
17984
18560
|
let currentSchema = initial.schema ?? null;
|
|
17985
18561
|
let currentTable = initial.table ?? null;
|
|
17986
18562
|
let loadGeneration = 0;
|
|
17987
18563
|
const tableSelectGuard = createAbortGuard();
|
|
17988
18564
|
let historyRefreshPending = null;
|
|
18565
|
+
let isRefreshingDatastores = false;
|
|
18566
|
+
let datastoreRefreshResult = null;
|
|
17989
18567
|
const dbSelect = document.createElement("select");
|
|
17990
18568
|
dbSelect.className = "db-file-select";
|
|
17991
18569
|
reloc(() => {
|
|
@@ -17997,9 +18575,29 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
17997
18575
|
reloc(() => {
|
|
17998
18576
|
schemaSelect.title = paneText().nav.selectSchema;
|
|
17999
18577
|
});
|
|
18578
|
+
const dbRefreshBtn = makeIconButton({
|
|
18579
|
+
label: paneText().nav.refreshDatastores,
|
|
18580
|
+
title: paneText().nav.refreshDatastoresTitle,
|
|
18581
|
+
pathD: SYNC_16_PATH,
|
|
18582
|
+
onClick: () => {
|
|
18583
|
+
refreshDatastoreList();
|
|
18584
|
+
}
|
|
18585
|
+
});
|
|
18586
|
+
dbRefreshBtn.classList.add("db-refresh-btn");
|
|
18587
|
+
const dbRefreshLabel = document.createElement("span");
|
|
18588
|
+
dbRefreshLabel.className = "db-refresh-label";
|
|
18589
|
+
dbRefreshBtn.appendChild(dbRefreshLabel);
|
|
18590
|
+
const dbRefreshResult = document.createElement("span");
|
|
18591
|
+
dbRefreshResult.className = "db-refresh-result";
|
|
18592
|
+
dbRefreshResult.hidden = true;
|
|
18593
|
+
dbRefreshResult.setAttribute("aria-live", "polite");
|
|
18594
|
+
syncDbRefreshButton();
|
|
18595
|
+
const dbSelectRow = document.createElement("div");
|
|
18596
|
+
dbSelectRow.className = "db-select-row";
|
|
18597
|
+
dbSelectRow.append(dbSelect, dbRefreshBtn, dbRefreshResult);
|
|
18000
18598
|
const dbToolbar = document.createElement("div");
|
|
18001
18599
|
dbToolbar.className = "db-toolbar";
|
|
18002
|
-
dbToolbar.append(
|
|
18600
|
+
dbToolbar.append(dbSelectRow, schemaSelect);
|
|
18003
18601
|
const tabBar = document.createElement("div");
|
|
18004
18602
|
tabBar.className = "db-tab-bar";
|
|
18005
18603
|
const tabData = createInnerTab("Data", true);
|
|
@@ -18073,7 +18671,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
18073
18671
|
const searchBtn = makeIconButton({
|
|
18074
18672
|
label: "Search",
|
|
18075
18673
|
title: "Search across tables",
|
|
18076
|
-
pathD:
|
|
18674
|
+
pathD: SEARCH_16_PATH,
|
|
18077
18675
|
onClick: () => setActiveTab("search")
|
|
18078
18676
|
});
|
|
18079
18677
|
const snapshotBtn = makeIconButton({
|
|
@@ -18091,6 +18689,8 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
18091
18689
|
});
|
|
18092
18690
|
reloc(() => {
|
|
18093
18691
|
const t2 = paneText().nav;
|
|
18692
|
+
localizeIconButton(dbRefreshBtn, t2.refreshDatastores, t2.refreshDatastoresTitle);
|
|
18693
|
+
syncDbRefreshButton();
|
|
18094
18694
|
localizeIconButton(queryBtn, t2.query, t2.queryTitle);
|
|
18095
18695
|
localizeIconButton(erBtn, t2.er, t2.erTitle);
|
|
18096
18696
|
localizeIconButton(searchBtn, t2.search, t2.searchTitle);
|
|
@@ -18145,7 +18745,13 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
18145
18745
|
},
|
|
18146
18746
|
getText: () => paneText(),
|
|
18147
18747
|
getEditable: () => isSqlKind(currentDbInfo?.kind),
|
|
18148
|
-
applyMutations: (mutations) => applyRowMutations(mutations)
|
|
18748
|
+
applyMutations: (mutations) => applyRowMutations(mutations),
|
|
18749
|
+
onRefreshComplete: ({ table: table2, filters }) => {
|
|
18750
|
+
if (filters.length === 0) {
|
|
18751
|
+
return;
|
|
18752
|
+
}
|
|
18753
|
+
refreshTableRowCount(table2);
|
|
18754
|
+
}
|
|
18149
18755
|
});
|
|
18150
18756
|
const editModeToggle = makePrefToggle({
|
|
18151
18757
|
title: paneText().edit.editModeTitle,
|
|
@@ -18177,7 +18783,10 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
18177
18783
|
});
|
|
18178
18784
|
if (initial.sqlDraft)
|
|
18179
18785
|
queryEditor.setSql(initial.sqlDraft, { silent: true });
|
|
18180
|
-
const schemaView = createSchemaView({
|
|
18786
|
+
const schemaView = createSchemaView({
|
|
18787
|
+
getText: () => paneText(),
|
|
18788
|
+
onRefresh: () => refreshCurrentSchemaView()
|
|
18789
|
+
});
|
|
18181
18790
|
const erDiagram = createErDiagram({ getText: () => paneText() });
|
|
18182
18791
|
const globalSearchView = createGlobalSearchView({
|
|
18183
18792
|
getDbId: () => currentDbInfo?.id || null,
|
|
@@ -18268,9 +18877,30 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
18268
18877
|
s3Explorer.el.hidden = true;
|
|
18269
18878
|
s3Explorer.sidebarSlot.hidden = true;
|
|
18270
18879
|
explorerSidebarHost.append(redisExplorer.sidebarSlot, esExplorer.sidebarSlot, s3Explorer.sidebarSlot);
|
|
18880
|
+
const noDatastoresPane = document.createElement("div");
|
|
18881
|
+
noDatastoresPane.className = "db-no-datastores";
|
|
18882
|
+
noDatastoresPane.hidden = true;
|
|
18883
|
+
function renderNoDatastoresEmpty() {
|
|
18884
|
+
const t2 = paneText().nav;
|
|
18885
|
+
setPaneEmpty(noDatastoresPane, t2.noDatastores, {
|
|
18886
|
+
hint: t2.noDatastoresHint,
|
|
18887
|
+
iconPath: ICON_PATH_SNAPSHOT
|
|
18888
|
+
});
|
|
18889
|
+
const actionRow = document.createElement("div");
|
|
18890
|
+
actionRow.className = "db-no-datastores-actions";
|
|
18891
|
+
const refresh = document.createElement("button");
|
|
18892
|
+
refresh.type = "button";
|
|
18893
|
+
refresh.className = "db-btn db-btn-primary db-no-datastores-action";
|
|
18894
|
+
refresh.textContent = t2.refreshDatastores;
|
|
18895
|
+
refresh.addEventListener("click", () => {
|
|
18896
|
+
refreshDatastoreList();
|
|
18897
|
+
});
|
|
18898
|
+
actionRow.appendChild(refresh);
|
|
18899
|
+
noDatastoresPane.querySelector(".db-pane-empty")?.appendChild(actionRow);
|
|
18900
|
+
}
|
|
18271
18901
|
const mainContent = document.createElement("div");
|
|
18272
18902
|
mainContent.className = "db-main-content";
|
|
18273
|
-
mainContent.append(tabBar, grid.el, queryEditor.el, schemaView.el, erDiagram.el, globalSearchView.el, snapshotView.el, redisExplorer.el, esExplorer.el, s3Explorer.el);
|
|
18903
|
+
mainContent.append(tabBar, grid.el, queryEditor.el, schemaView.el, erDiagram.el, globalSearchView.el, snapshotView.el, redisExplorer.el, esExplorer.el, s3Explorer.el, noDatastoresPane);
|
|
18274
18904
|
queryEditor.el.hidden = true;
|
|
18275
18905
|
globalSearchView.el.hidden = true;
|
|
18276
18906
|
snapshotView.el.hidden = true;
|
|
@@ -18381,6 +19011,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
18381
19011
|
function applyVisibility() {
|
|
18382
19012
|
const sqlMode = isSqlKind(currentDbInfo?.kind);
|
|
18383
19013
|
const visibility = computeVisibility(currentDbInfo?.kind, currentTab, userPrefersHistoryOpen);
|
|
19014
|
+
noDatastoresPane.hidden = !noDatastoresAvailable;
|
|
18384
19015
|
toolsSection.hidden = visibility.toolsHidden;
|
|
18385
19016
|
prefsBar.hidden = visibility.toolsHidden;
|
|
18386
19017
|
historyDock.hidden = visibility.historyTabStripHidden;
|
|
@@ -18401,6 +19032,28 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
18401
19032
|
esExplorer.sidebarSlot.hidden = visibility.esHidden;
|
|
18402
19033
|
s3Explorer.sidebarSlot.hidden = visibility.s3Hidden;
|
|
18403
19034
|
explorerSidebarHost.hidden = visibility.redisHidden && visibility.esHidden && visibility.s3Hidden;
|
|
19035
|
+
if (noDatastoresAvailable) {
|
|
19036
|
+
toolsSection.hidden = true;
|
|
19037
|
+
prefsBar.hidden = true;
|
|
19038
|
+
historyDock.hidden = true;
|
|
19039
|
+
historyResizer.hidden = true;
|
|
19040
|
+
historyPane.hidden = true;
|
|
19041
|
+
tableList.el.hidden = true;
|
|
19042
|
+
tabBar.hidden = true;
|
|
19043
|
+
grid.el.hidden = true;
|
|
19044
|
+
queryEditor.el.hidden = true;
|
|
19045
|
+
schemaView.el.hidden = true;
|
|
19046
|
+
erDiagram.el.hidden = true;
|
|
19047
|
+
globalSearchView.el.hidden = true;
|
|
19048
|
+
snapshotView.el.hidden = true;
|
|
19049
|
+
redisExplorer.el.hidden = true;
|
|
19050
|
+
esExplorer.el.hidden = true;
|
|
19051
|
+
s3Explorer.el.hidden = true;
|
|
19052
|
+
redisExplorer.sidebarSlot.hidden = true;
|
|
19053
|
+
esExplorer.sidebarSlot.hidden = true;
|
|
19054
|
+
s3Explorer.sidebarSlot.hidden = true;
|
|
19055
|
+
explorerSidebarHost.hidden = true;
|
|
19056
|
+
}
|
|
18404
19057
|
if (!sqlMode) {
|
|
18405
19058
|
queryBtn.classList.remove("active");
|
|
18406
19059
|
erBtn.classList.remove("active");
|
|
@@ -18551,11 +19204,59 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
18551
19204
|
errorPrefix: "failed to fetch schema"
|
|
18552
19205
|
});
|
|
18553
19206
|
}
|
|
19207
|
+
function syncCachedTableRowCount(table2, rowCount) {
|
|
19208
|
+
if (!schemaCache)
|
|
19209
|
+
return;
|
|
19210
|
+
let changed = false;
|
|
19211
|
+
const tables = schemaCache.tables.map((entry) => {
|
|
19212
|
+
if (entry.name !== table2 || entry.rowCount === rowCount)
|
|
19213
|
+
return entry;
|
|
19214
|
+
changed = true;
|
|
19215
|
+
return { ...entry, rowCount };
|
|
19216
|
+
});
|
|
19217
|
+
if (!changed)
|
|
19218
|
+
return;
|
|
19219
|
+
schemaCache = { ...schemaCache, tables };
|
|
19220
|
+
tableList.updateRowCount(table2, rowCount);
|
|
19221
|
+
}
|
|
19222
|
+
async function fetchTableRowCount(table2, dbId, schema) {
|
|
19223
|
+
const params = new URLSearchParams({ db: dbId, table: table2 });
|
|
19224
|
+
if (schema)
|
|
19225
|
+
params.set("schema", schema);
|
|
19226
|
+
return logSqlFetch({
|
|
19227
|
+
url: `/_db/table-count?${params}`,
|
|
19228
|
+
kind: "query",
|
|
19229
|
+
label: `_db/table-count ${table2}`,
|
|
19230
|
+
errorPrefix: "failed to fetch table count",
|
|
19231
|
+
rowCountOf: (r2) => r2.rowCount ?? undefined
|
|
19232
|
+
});
|
|
19233
|
+
}
|
|
19234
|
+
async function refreshTableRowCount(table2) {
|
|
19235
|
+
const dbId = currentDbInfo?.id;
|
|
19236
|
+
if (!dbId)
|
|
19237
|
+
return;
|
|
19238
|
+
const schema = currentSchema;
|
|
19239
|
+
const generation = loadGeneration;
|
|
19240
|
+
try {
|
|
19241
|
+
const data = await fetchTableRowCount(table2, dbId, schema);
|
|
19242
|
+
if (generation !== loadGeneration || currentDbInfo?.id !== dbId || currentSchema !== schema || currentTable !== table2) {
|
|
19243
|
+
return;
|
|
19244
|
+
}
|
|
19245
|
+
syncCachedTableRowCount(table2, data.rowCount);
|
|
19246
|
+
} catch (err) {
|
|
19247
|
+
if (!isAbortError2(err)) {
|
|
19248
|
+
console.warn(`failed to refresh table count: ${errorMessage(err)}`);
|
|
19249
|
+
}
|
|
19250
|
+
}
|
|
19251
|
+
}
|
|
18554
19252
|
async function fetchTablePage(table2, offset, limit, sort, filters, signal, eq = []) {
|
|
18555
19253
|
if (!currentDbInfo)
|
|
18556
19254
|
throw new Error("no database selected");
|
|
19255
|
+
const requestDbId = currentDbInfo.id;
|
|
19256
|
+
const requestSchema = currentSchema;
|
|
19257
|
+
const requestGeneration = loadGeneration;
|
|
18557
19258
|
const params = new URLSearchParams({
|
|
18558
|
-
db:
|
|
19259
|
+
db: requestDbId,
|
|
18559
19260
|
table: table2,
|
|
18560
19261
|
offset: String(offset),
|
|
18561
19262
|
limit: String(limit)
|
|
@@ -18571,7 +19272,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
18571
19272
|
if (eq.length > 0) {
|
|
18572
19273
|
params.set("eq", JSON.stringify(eq));
|
|
18573
19274
|
}
|
|
18574
|
-
|
|
19275
|
+
const data = await logSqlFetch({
|
|
18575
19276
|
url: `/_db/table?${params}`,
|
|
18576
19277
|
init: signal ? { signal } : undefined,
|
|
18577
19278
|
kind: "query",
|
|
@@ -18580,6 +19281,10 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
18580
19281
|
errorPrefix: "failed to fetch table",
|
|
18581
19282
|
rowCountOf: (r2) => r2.rows.length
|
|
18582
19283
|
});
|
|
19284
|
+
if (filters.length === 0 && eq.length === 0 && currentDbInfo?.id === requestDbId && currentSchema === requestSchema && currentTable === table2 && requestGeneration === loadGeneration) {
|
|
19285
|
+
syncCachedTableRowCount(table2, data.totalRows);
|
|
19286
|
+
}
|
|
19287
|
+
return data;
|
|
18583
19288
|
}
|
|
18584
19289
|
function fetchRelatedPage(table2, offset, limit, sort, filters, eq, signal) {
|
|
18585
19290
|
return fetchTablePage(table2, offset, limit, sort, filters, signal, eq);
|
|
@@ -18891,6 +19596,47 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
18891
19596
|
const columns = await fetchColumns(table2);
|
|
18892
19597
|
schemaView.render(table2, columns, schemaCache?.indexes || []);
|
|
18893
19598
|
}
|
|
19599
|
+
async function refreshCurrentSchemaView() {
|
|
19600
|
+
if (!currentDbInfo || !currentTable)
|
|
19601
|
+
return;
|
|
19602
|
+
const generation = loadGeneration;
|
|
19603
|
+
const dbId = currentDbInfo.id;
|
|
19604
|
+
const table2 = currentTable;
|
|
19605
|
+
schemaView.setRefreshBusy(true);
|
|
19606
|
+
try {
|
|
19607
|
+
const schema = await fetchSchema(dbId);
|
|
19608
|
+
if (generation !== loadGeneration || currentDbInfo?.id !== dbId || currentTable !== table2) {
|
|
19609
|
+
return;
|
|
19610
|
+
}
|
|
19611
|
+
currentSchema = schema.schema || currentSchema;
|
|
19612
|
+
schemaCache = schema;
|
|
19613
|
+
tableList.render(schema.tables);
|
|
19614
|
+
const nextTable = schema.tables.some((entry) => entry.name === table2) ? table2 : schema.tables[0]?.name;
|
|
19615
|
+
if (!nextTable) {
|
|
19616
|
+
currentTable = null;
|
|
19617
|
+
grid.clear();
|
|
19618
|
+
schemaView.clear();
|
|
19619
|
+
erDiagram.clear();
|
|
19620
|
+
cb.onStateChange();
|
|
19621
|
+
return;
|
|
19622
|
+
}
|
|
19623
|
+
currentTable = nextTable;
|
|
19624
|
+
tableList.setActive(nextTable);
|
|
19625
|
+
const columns = await fetchColumns(nextTable);
|
|
19626
|
+
if (generation !== loadGeneration || currentDbInfo?.id !== dbId || currentTable !== nextTable) {
|
|
19627
|
+
return;
|
|
19628
|
+
}
|
|
19629
|
+
schemaView.render(nextTable, columns, schema.indexes || []);
|
|
19630
|
+
cb.onStateChange();
|
|
19631
|
+
} catch (err) {
|
|
19632
|
+
if (generation !== loadGeneration || currentDbInfo?.id !== dbId || isAbortError2(err)) {
|
|
19633
|
+
return;
|
|
19634
|
+
}
|
|
19635
|
+
setTableListStatus(errorMessage(err), { error: true });
|
|
19636
|
+
} finally {
|
|
19637
|
+
schemaView.setRefreshBusy(false);
|
|
19638
|
+
}
|
|
19639
|
+
}
|
|
18894
19640
|
async function showDdl(table2) {
|
|
18895
19641
|
if (!currentDbInfo)
|
|
18896
19642
|
return;
|
|
@@ -18935,6 +19681,54 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
18935
19681
|
schemaSelect.addEventListener("change", () => {
|
|
18936
19682
|
handleSchemaSelectChange();
|
|
18937
19683
|
});
|
|
19684
|
+
function syncDbRefreshButton() {
|
|
19685
|
+
const text2 = paneText().nav;
|
|
19686
|
+
dbRefreshLabel.textContent = isRefreshingDatastores ? text2.refreshDatastoresBusy : text2.refreshDatastoresShort;
|
|
19687
|
+
dbRefreshBtn.setAttribute("aria-busy", isRefreshingDatastores ? "true" : "false");
|
|
19688
|
+
syncDatastoreRefreshResult();
|
|
19689
|
+
}
|
|
19690
|
+
function syncDatastoreRefreshResult() {
|
|
19691
|
+
const result = datastoreRefreshResult;
|
|
19692
|
+
dbRefreshResult.hidden = !result;
|
|
19693
|
+
dbRefreshResult.classList.toggle("changed", !!result && (result.added > 0 || result.removed > 0));
|
|
19694
|
+
if (!result)
|
|
19695
|
+
return;
|
|
19696
|
+
const text2 = paneText().nav;
|
|
19697
|
+
dbRefreshResult.textContent = result.added > 0 || result.removed > 0 ? text2.refreshDatastoresChanged(result.added, result.removed) : text2.refreshDatastoresUnchanged;
|
|
19698
|
+
}
|
|
19699
|
+
function diffDatastoreFiles(before, after) {
|
|
19700
|
+
const beforeIds = new Set(before.map((file) => file.id));
|
|
19701
|
+
const afterIds = new Set(after.map((file) => file.id));
|
|
19702
|
+
let added = 0;
|
|
19703
|
+
let removed = 0;
|
|
19704
|
+
for (const id of afterIds) {
|
|
19705
|
+
if (!beforeIds.has(id))
|
|
19706
|
+
added++;
|
|
19707
|
+
}
|
|
19708
|
+
for (const id of beforeIds) {
|
|
19709
|
+
if (!afterIds.has(id))
|
|
19710
|
+
removed++;
|
|
19711
|
+
}
|
|
19712
|
+
return { added, removed };
|
|
19713
|
+
}
|
|
19714
|
+
async function refreshDatastoreList() {
|
|
19715
|
+
if (dbRefreshBtn.disabled)
|
|
19716
|
+
return;
|
|
19717
|
+
const beforeFiles = [...lastFiles];
|
|
19718
|
+
isRefreshingDatastores = true;
|
|
19719
|
+
dbRefreshBtn.disabled = true;
|
|
19720
|
+
dbRefreshBtn.classList.add("spinning");
|
|
19721
|
+
syncDbRefreshButton();
|
|
19722
|
+
try {
|
|
19723
|
+
await outerDeps.refreshDatastores();
|
|
19724
|
+
datastoreRefreshResult = cb.isActive() ? diffDatastoreFiles(beforeFiles, lastFiles) : null;
|
|
19725
|
+
} finally {
|
|
19726
|
+
isRefreshingDatastores = false;
|
|
19727
|
+
dbRefreshBtn.classList.remove("spinning");
|
|
19728
|
+
dbRefreshBtn.disabled = false;
|
|
19729
|
+
syncDbRefreshButton();
|
|
19730
|
+
}
|
|
19731
|
+
}
|
|
18938
19732
|
async function handleSchemaSelectChange() {
|
|
18939
19733
|
if (!currentDbInfo || !isPostgresKind(currentDbInfo.kind))
|
|
18940
19734
|
return;
|
|
@@ -18963,6 +19757,8 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
18963
19757
|
const dbId = dbSelect.value;
|
|
18964
19758
|
if (!dbId)
|
|
18965
19759
|
return;
|
|
19760
|
+
datastoreRefreshResult = null;
|
|
19761
|
+
syncDatastoreRefreshResult();
|
|
18966
19762
|
const generation = ++loadGeneration;
|
|
18967
19763
|
const file = lastFiles.find((f2) => f2.id === dbId);
|
|
18968
19764
|
const option = dbSelect.selectedOptions[0];
|
|
@@ -18998,6 +19794,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
18998
19794
|
return;
|
|
18999
19795
|
const files = filesResponse.files;
|
|
19000
19796
|
lastFiles = files;
|
|
19797
|
+
noDatastoresAvailable = files.length === 0;
|
|
19001
19798
|
if (filesResponse.truncated) {
|
|
19002
19799
|
showDockerNotice(paneText().nav.dockerLimitReached);
|
|
19003
19800
|
} else {
|
|
@@ -19010,6 +19807,20 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
19010
19807
|
opt.textContent = paneText().nav.noDatastores;
|
|
19011
19808
|
dbSelect.appendChild(opt);
|
|
19012
19809
|
dbSelect.disabled = true;
|
|
19810
|
+
currentDbInfo = null;
|
|
19811
|
+
currentSchema = null;
|
|
19812
|
+
currentTable = null;
|
|
19813
|
+
schemaCache = null;
|
|
19814
|
+
renderSchemaOptions([], null);
|
|
19815
|
+
tableList.render([]);
|
|
19816
|
+
grid.clear();
|
|
19817
|
+
schemaView.clear();
|
|
19818
|
+
erDiagram.clear();
|
|
19819
|
+
redisExplorer.clear();
|
|
19820
|
+
esExplorer.clear();
|
|
19821
|
+
s3Explorer.clear();
|
|
19822
|
+
renderNoDatastoresEmpty();
|
|
19823
|
+
applyVisibility();
|
|
19013
19824
|
cb.onStateChange();
|
|
19014
19825
|
return;
|
|
19015
19826
|
}
|
|
@@ -19204,6 +20015,8 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
19204
20015
|
return target;
|
|
19205
20016
|
}
|
|
19206
20017
|
function getLabel() {
|
|
20018
|
+
if (noDatastoresAvailable)
|
|
20019
|
+
return paneText().nav.noDatastoreTab;
|
|
19207
20020
|
if (!currentDbInfo)
|
|
19208
20021
|
return labelFromDbId(initial.dbId);
|
|
19209
20022
|
const suffix = currentSchema ? ` / ${currentSchema}` : "";
|
|
@@ -19242,6 +20055,8 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
19242
20055
|
function localizePane() {
|
|
19243
20056
|
for (const fn of paneLocalizers)
|
|
19244
20057
|
fn();
|
|
20058
|
+
if (noDatastoresAvailable)
|
|
20059
|
+
renderNoDatastoresEmpty();
|
|
19245
20060
|
grid.localize();
|
|
19246
20061
|
schemaView.localize();
|
|
19247
20062
|
erDiagram.localize();
|
|
@@ -19266,7 +20081,6 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
19266
20081
|
}
|
|
19267
20082
|
var ICON_PATH_QUERY = "M5.72 4.22a.75.75 0 0 1 0 1.06L2.81 8l2.91 2.72a.75.75 0 1 1-1.06 1.06L1.22 8.53a.75.75 0 0 1 0-1.06l3.44-3.25a.75.75 0 0 1 1.06 0Zm4.56 0a.75.75 0 0 1 1.06 0l3.44 3.25a.75.75 0 0 1 0 1.06l-3.44 3.25a.75.75 0 1 1-1.06-1.06L13.19 8l-2.91-2.72a.75.75 0 0 1 0-1.06Z";
|
|
19268
20083
|
var ICON_PATH_ER = "M1.5 1.75A.75.75 0 0 1 2.25 1h4.5a.75.75 0 0 1 .75.75v3.5h2v-1.5A.75.75 0 0 1 10.25 3h3.5a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-.75.75h-3.5a.75.75 0 0 1-.75-.75V6.5h-2v3h2v-.75A.75.75 0 0 1 10.25 8h3.5a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-.75.75h-3.5a.75.75 0 0 1-.75-.75v-1.5h-2v3.5a.75.75 0 0 1-.75.75h-4.5a.75.75 0 0 1-.75-.75v-3.5A.75.75 0 0 1 2.25 9h4.5a.75.75 0 0 1 .75.75v.75h-.5v-1H3v3h3V11h.5v-.75a.75.75 0 0 0-.75-.75H3V6.5h2.5V2.5H3Z";
|
|
19269
|
-
var ICON_PATH_SEARCH = "M10.68 11.74a6 6 0 0 1-7.917-8.984 6 6 0 0 1 8.997 7.905l3.05 3.05a.75.75 0 1 1-1.06 1.06l-3.07-3.03ZM11.5 7a4.499 4.499 0 1 1-8.997 0A4.499 4.499 0 0 1 11.5 7Z";
|
|
19270
20084
|
var ICON_PATH_SNAPSHOT = "M3.5 1.75A1.75 1.75 0 0 1 5.25 0h5.5A1.75 1.75 0 0 1 12.5 1.75v.5h1.75A1.75 1.75 0 0 1 16 4v9.25A1.75 1.75 0 0 1 14.25 15H1.75A1.75 1.75 0 0 1 0 13.25V4a1.75 1.75 0 0 1 1.75-1.75H3.5v-.5Zm1.5.5v.5h6v-.5a.25.25 0 0 0-.25-.25h-5.5a.25.25 0 0 0-.25.25Zm-3.25 2a.25.25 0 0 0-.25.25v9.25c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25V4a.25.25 0 0 0-.25-.25H1.75ZM8 6a2.75 2.75 0 1 0 0 5.5 2.75 2.75 0 0 0 0-5.5Z";
|
|
19271
20085
|
var ICON_PATH_EDIT_MODE = "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.61Zm.176 4.823L9.75 4.81l-6.286 6.287a.247.247 0 0 0-.064.108l-.558 1.953 1.953-.558a.249.249 0 0 0 .108-.064l6.286-6.286Zm1.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-.354L12.427 2.49Z";
|
|
19272
20086
|
function makeIconButton(opts) {
|
|
@@ -19897,6 +20711,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
19897
20711
|
setDbUiPref,
|
|
19898
20712
|
onDbUiPrefChange,
|
|
19899
20713
|
loadSqlHistory,
|
|
20714
|
+
refreshDatastores,
|
|
19900
20715
|
sessionLog
|
|
19901
20716
|
}, {
|
|
19902
20717
|
tabId: id,
|
|
@@ -20208,6 +21023,36 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
20208
21023
|
}).then(() => doEnter(seq, db, schema, table2, view, options));
|
|
20209
21024
|
await enterQueue;
|
|
20210
21025
|
}
|
|
21026
|
+
async function refreshDatastores() {
|
|
21027
|
+
const seq = lifecycleSeq;
|
|
21028
|
+
enterQueue = enterQueue.catch(() => {
|
|
21029
|
+
return;
|
|
21030
|
+
}).then(() => doRefreshDatastores(seq));
|
|
21031
|
+
await enterQueue;
|
|
21032
|
+
}
|
|
21033
|
+
async function doRefreshDatastores(seq) {
|
|
21034
|
+
if (seq !== lifecycleSeq)
|
|
21035
|
+
return;
|
|
21036
|
+
dbFilesCache = null;
|
|
21037
|
+
if (!mounted || !activeTabId)
|
|
21038
|
+
return;
|
|
21039
|
+
const id = activeTabId;
|
|
21040
|
+
const entry = tabsById.get(id);
|
|
21041
|
+
if (!entry)
|
|
21042
|
+
return;
|
|
21043
|
+
const pendingInitialEnter = ensureInitialEnter(id);
|
|
21044
|
+
if (pendingInitialEnter)
|
|
21045
|
+
await pendingInitialEnter;
|
|
21046
|
+
if (!mounted || activeTabId !== id)
|
|
21047
|
+
return;
|
|
21048
|
+
const state = entry.pane.getState();
|
|
21049
|
+
await entry.pane.enter(state.dbId ?? undefined, state.schema ?? undefined, state.table ?? undefined, state.view, { autoSelectFirst: state.dbId !== null });
|
|
21050
|
+
if (!mounted || activeTabId !== id)
|
|
21051
|
+
return;
|
|
21052
|
+
refreshChipLabel(id);
|
|
21053
|
+
syncActiveRoute();
|
|
21054
|
+
scheduleSave();
|
|
21055
|
+
}
|
|
20211
21056
|
function leave() {
|
|
20212
21057
|
if (!mounted)
|
|
20213
21058
|
return;
|
|
@@ -20285,6 +21130,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
20285
21130
|
leave,
|
|
20286
21131
|
handleSse,
|
|
20287
21132
|
localize,
|
|
21133
|
+
refresh: refreshDatastores,
|
|
20288
21134
|
getDbUiPref,
|
|
20289
21135
|
setDbUiPref,
|
|
20290
21136
|
onDbUiPrefChange
|
|
@@ -20483,6 +21329,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
20483
21329
|
getServerGeneration,
|
|
20484
21330
|
setServerGeneration,
|
|
20485
21331
|
invalidateRepoSidebar,
|
|
21332
|
+
diffText,
|
|
20486
21333
|
getDiffRoot,
|
|
20487
21334
|
getEmptyPane,
|
|
20488
21335
|
isEmbeddedDiffMode
|
|
@@ -20543,7 +21390,9 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
20543
21390
|
if (!button)
|
|
20544
21391
|
return;
|
|
20545
21392
|
button.setAttribute("aria-pressed", expanded ? "true" : "false");
|
|
20546
|
-
|
|
21393
|
+
const label = expanded ? "Collapse expanded lines" : "Expand all lines";
|
|
21394
|
+
button.title = label;
|
|
21395
|
+
button.setAttribute("aria-label", label);
|
|
20547
21396
|
button.innerHTML = expanded ? iconSvg("octicon-fold", COLLAPSE_ALL_16_PATHS) : iconSvg("octicon-unfold", EXPAND_ALL_16_PATHS);
|
|
20548
21397
|
}
|
|
20549
21398
|
function setProjectBranch(branch) {
|
|
@@ -20554,25 +21403,131 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
20554
21403
|
el.textContent = branch;
|
|
20555
21404
|
el.title = branch ? `Current branch: ${branch}` : "";
|
|
20556
21405
|
}
|
|
21406
|
+
let metaFilesForViewedProgress = [];
|
|
21407
|
+
function viewedProgressFor(files) {
|
|
21408
|
+
const total = files.length;
|
|
21409
|
+
const viewed = files.filter((file) => STATE.viewedFiles.has(file.path)).length;
|
|
21410
|
+
return { viewed, total };
|
|
21411
|
+
}
|
|
21412
|
+
function applyViewedProgressChipState(chip, viewed, total) {
|
|
21413
|
+
chip.textContent = diffText().viewedProgress(viewed, total);
|
|
21414
|
+
chip.classList.toggle("chip-viewed-empty", viewed === 0);
|
|
21415
|
+
chip.classList.toggle("chip-viewed-partial", viewed > 0 && viewed < total);
|
|
21416
|
+
chip.classList.toggle("chip-viewed-done", total > 0 && viewed === total);
|
|
21417
|
+
}
|
|
21418
|
+
function syncViewedProgressChip() {
|
|
21419
|
+
const chip = document.querySelector("#meta .chip-viewed");
|
|
21420
|
+
if (chip) {
|
|
21421
|
+
const { viewed, total } = viewedProgressFor(metaFilesForViewedProgress);
|
|
21422
|
+
if (total <= 0)
|
|
21423
|
+
chip.remove();
|
|
21424
|
+
else
|
|
21425
|
+
applyViewedProgressChipState(chip, viewed, total);
|
|
21426
|
+
}
|
|
21427
|
+
syncNextUnviewedButton();
|
|
21428
|
+
}
|
|
21429
|
+
function applyNextUnviewedButtonState(button, hasUnviewed) {
|
|
21430
|
+
const text2 = diffText();
|
|
21431
|
+
button.disabled = !hasUnviewed;
|
|
21432
|
+
button.textContent = hasUnviewed ? text2.nextUnviewed : text2.allViewed;
|
|
21433
|
+
button.title = hasUnviewed ? text2.nextUnviewedTitle : text2.allViewedTitle;
|
|
21434
|
+
}
|
|
21435
|
+
function syncNextUnviewedButton() {
|
|
21436
|
+
const button = document.querySelector("#meta .chip-next-unviewed");
|
|
21437
|
+
if (!button)
|
|
21438
|
+
return;
|
|
21439
|
+
const { total } = viewedProgressFor(metaFilesForViewedProgress);
|
|
21440
|
+
if (total <= 0) {
|
|
21441
|
+
button.remove();
|
|
21442
|
+
return;
|
|
21443
|
+
}
|
|
21444
|
+
applyNextUnviewedButtonState(button, nextUnviewedFilePath() !== null);
|
|
21445
|
+
}
|
|
21446
|
+
function nextUnviewedFilePath() {
|
|
21447
|
+
if (isRepositorySidebarMode())
|
|
21448
|
+
return null;
|
|
21449
|
+
const items = $$("#filelist li[data-path]:not(.hidden):not(.hidden-by-tests)");
|
|
21450
|
+
if (items.length === 0)
|
|
21451
|
+
return null;
|
|
21452
|
+
const currentIndex = items.findIndex((li) => li.classList.contains("active"));
|
|
21453
|
+
for (let offset = 1;offset <= items.length; offset++) {
|
|
21454
|
+
const idx = (currentIndex + offset + items.length) % items.length;
|
|
21455
|
+
const li = items[idx];
|
|
21456
|
+
const path = li.dataset.path || "";
|
|
21457
|
+
const viewed = STATE.viewedFiles.has(path) || li.classList.contains("viewed");
|
|
21458
|
+
if (path && !viewed)
|
|
21459
|
+
return path;
|
|
21460
|
+
}
|
|
21461
|
+
return null;
|
|
21462
|
+
}
|
|
21463
|
+
function scrollToNextUnviewedFile() {
|
|
21464
|
+
const path = nextUnviewedFilePath();
|
|
21465
|
+
if (!path)
|
|
21466
|
+
return false;
|
|
21467
|
+
scrollToFile(path, undefined, { reveal: true });
|
|
21468
|
+
return true;
|
|
21469
|
+
}
|
|
20557
21470
|
function renderMeta(meta) {
|
|
20558
21471
|
const el = $("#meta");
|
|
20559
21472
|
if (!meta) {
|
|
20560
21473
|
el.textContent = "";
|
|
21474
|
+
metaFilesForViewedProgress = [];
|
|
20561
21475
|
return;
|
|
20562
21476
|
}
|
|
20563
21477
|
setProjectName(meta.project || "");
|
|
20564
21478
|
setProjectBranch(meta.branch || "");
|
|
21479
|
+
metaFilesForViewedProgress = meta.files || [];
|
|
20565
21480
|
el.innerHTML = "";
|
|
21481
|
+
const text2 = diffText();
|
|
20566
21482
|
if (meta.totals) {
|
|
20567
|
-
const
|
|
20568
|
-
|
|
20569
|
-
|
|
20570
|
-
el.appendChild(
|
|
21483
|
+
const files = document.createElement("span");
|
|
21484
|
+
files.className = "chip chip-files";
|
|
21485
|
+
files.textContent = text2.files(meta.totals.files);
|
|
21486
|
+
el.appendChild(files);
|
|
21487
|
+
const add2 = document.createElement("span");
|
|
21488
|
+
add2.className = "chip chip-add";
|
|
21489
|
+
add2.textContent = `+${meta.totals.additions}`;
|
|
21490
|
+
el.appendChild(add2);
|
|
21491
|
+
const del = document.createElement("span");
|
|
21492
|
+
del.className = "chip chip-del";
|
|
21493
|
+
del.textContent = `−${meta.totals.deletions}`;
|
|
21494
|
+
el.appendChild(del);
|
|
21495
|
+
}
|
|
21496
|
+
const kinds = summarizeDiffFileKinds(meta.files);
|
|
21497
|
+
const kindChip = (className, label, count) => {
|
|
21498
|
+
if (count <= 0)
|
|
21499
|
+
return;
|
|
21500
|
+
const chip = document.createElement("span");
|
|
21501
|
+
chip.className = `chip ${className}`;
|
|
21502
|
+
chip.textContent = `${count} ${label}`;
|
|
21503
|
+
el.appendChild(chip);
|
|
21504
|
+
};
|
|
21505
|
+
kindChip("chip-added", text2.kindAdded, kinds.added);
|
|
21506
|
+
kindChip("chip-deleted", text2.kindDeleted, kinds.deleted);
|
|
21507
|
+
kindChip("chip-renamed", text2.kindRenamed, kinds.renamed);
|
|
21508
|
+
kindChip("chip-heavy", text2.kindHeavy, kinds.heavy);
|
|
21509
|
+
kindChip("chip-binary", text2.kindBinary, kinds.binary);
|
|
21510
|
+
kindChip("chip-media", text2.kindMedia, kinds.media);
|
|
21511
|
+
const viewedProgress = viewedProgressFor(metaFilesForViewedProgress);
|
|
21512
|
+
if (viewedProgress.total > 0) {
|
|
21513
|
+
const viewed = document.createElement("span");
|
|
21514
|
+
viewed.className = "chip chip-viewed";
|
|
21515
|
+
viewed.title = text2.viewedProgressTitle;
|
|
21516
|
+
applyViewedProgressChipState(viewed, viewedProgress.viewed, viewedProgress.total);
|
|
21517
|
+
el.appendChild(viewed);
|
|
21518
|
+
const nextUnviewed = document.createElement("button");
|
|
21519
|
+
nextUnviewed.type = "button";
|
|
21520
|
+
nextUnviewed.className = "chip chip-next-unviewed";
|
|
21521
|
+
applyNextUnviewedButtonState(nextUnviewed, viewedProgress.viewed < viewedProgress.total);
|
|
21522
|
+
nextUnviewed.addEventListener("click", () => {
|
|
21523
|
+
scrollToNextUnviewedFile();
|
|
21524
|
+
});
|
|
21525
|
+
el.appendChild(nextUnviewed);
|
|
20571
21526
|
}
|
|
20572
21527
|
const u2 = document.createElement("span");
|
|
20573
|
-
u2.className = "updated
|
|
20574
|
-
u2.title =
|
|
20575
|
-
u2.textContent =
|
|
21528
|
+
u2.className = "chip chip-updated";
|
|
21529
|
+
u2.title = text2.updatedTitle;
|
|
21530
|
+
u2.textContent = text2.updated(new Date().toLocaleTimeString([], { hour12: false }));
|
|
20576
21531
|
el.appendChild(u2);
|
|
20577
21532
|
}
|
|
20578
21533
|
let SUPPRESS_SPY_UNTIL = 0;
|
|
@@ -20629,13 +21584,13 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
20629
21584
|
window.addEventListener("touchmove", () => {
|
|
20630
21585
|
REANCHOR_UNTIL = 0;
|
|
20631
21586
|
}, { passive: true });
|
|
20632
|
-
function scrollToFile(path, line) {
|
|
21587
|
+
function scrollToFile(path, line, options) {
|
|
20633
21588
|
const card = document.querySelector(diffCardSelector(path));
|
|
20634
21589
|
if (!card)
|
|
20635
21590
|
return;
|
|
20636
21591
|
if (line)
|
|
20637
21592
|
REANCHOR_UNTIL = performance.now() + 4000;
|
|
20638
|
-
markActive(path);
|
|
21593
|
+
markActive(path, { reveal: options?.reveal });
|
|
20639
21594
|
SUPPRESS_SPY_UNTIL = performance.now() + 1500;
|
|
20640
21595
|
const onEnd = () => {
|
|
20641
21596
|
SUPPRESS_SPY_UNTIL = 0;
|
|
@@ -20663,6 +21618,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
20663
21618
|
const viewed = STATE.viewedFiles.has(path);
|
|
20664
21619
|
syncViewedCardDisplay(card, viewed);
|
|
20665
21620
|
});
|
|
21621
|
+
syncViewedProgressChip();
|
|
20666
21622
|
}
|
|
20667
21623
|
let CLIENT_REQ_SEQ = 0;
|
|
20668
21624
|
const LOAD_QUEUE = [];
|
|
@@ -20876,6 +21832,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
20876
21832
|
setupScrollSpy();
|
|
20877
21833
|
scrollSpyInstalled = true;
|
|
20878
21834
|
}
|
|
21835
|
+
syncViewedProgressChip();
|
|
20879
21836
|
return {
|
|
20880
21837
|
structureChanged: false,
|
|
20881
21838
|
invalidatedCards,
|
|
@@ -21213,7 +22170,9 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
21213
22170
|
const button = card.querySelector(".gdp-file-toggle");
|
|
21214
22171
|
if (button) {
|
|
21215
22172
|
button.setAttribute("aria-expanded", collapsed ? "false" : "true");
|
|
21216
|
-
|
|
22173
|
+
const toggleLabel = collapsed ? "Expand file" : "Collapse file";
|
|
22174
|
+
button.title = toggleLabel;
|
|
22175
|
+
button.setAttribute("aria-label", toggleLabel);
|
|
21217
22176
|
}
|
|
21218
22177
|
const unfold = card.querySelector(".gdp-file-unfold");
|
|
21219
22178
|
if (unfold)
|
|
@@ -21310,6 +22269,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
21310
22269
|
toggle.type = "button";
|
|
21311
22270
|
toggle.className = "gdp-file-header-icon gdp-file-toggle";
|
|
21312
22271
|
toggle.title = "Collapse file";
|
|
22272
|
+
toggle.setAttribute("aria-label", "Collapse file");
|
|
21313
22273
|
toggle.setAttribute("aria-expanded", "true");
|
|
21314
22274
|
toggle.innerHTML = iconSvg("octicon-chevron-down", CHEVRON_DOWN_16_PATH);
|
|
21315
22275
|
toggle.addEventListener("click", (e2) => {
|
|
@@ -21331,6 +22291,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
21331
22291
|
copy.type = "button";
|
|
21332
22292
|
copy.className = "gdp-file-header-icon gdp-copy-path";
|
|
21333
22293
|
copy.title = "copy file path";
|
|
22294
|
+
copy.setAttribute("aria-label", "copy file path");
|
|
21334
22295
|
copy.innerHTML = iconSvg("octicon-copy", COPY_16_PATHS);
|
|
21335
22296
|
copy.addEventListener("click", async (e2) => {
|
|
21336
22297
|
e2.stopPropagation();
|
|
@@ -21671,6 +22632,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
21671
22632
|
addExpandHunksUI,
|
|
21672
22633
|
scheduleIdleHighlight,
|
|
21673
22634
|
scrollToFile,
|
|
22635
|
+
scrollToNextUnviewedFile,
|
|
21674
22636
|
prefetchByPath,
|
|
21675
22637
|
applyDiffRouteFocus,
|
|
21676
22638
|
clearDiffLineFocus,
|
|
@@ -21899,12 +22861,17 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
21899
22861
|
deps.clearLoadQueue();
|
|
21900
22862
|
if (deps.empty) {
|
|
21901
22863
|
deps.empty.classList.remove("hidden");
|
|
22864
|
+
deps.empty.classList.remove("empty-with-actions");
|
|
22865
|
+
const text2 = deps.emptyText();
|
|
21902
22866
|
const h2 = deps.empty.querySelector("h2");
|
|
21903
22867
|
if (h2)
|
|
21904
|
-
h2.textContent =
|
|
22868
|
+
h2.textContent = text2.noCommitSelectedTitle;
|
|
21905
22869
|
const p2 = deps.empty.querySelector("p");
|
|
21906
22870
|
if (p2)
|
|
21907
|
-
p2.textContent =
|
|
22871
|
+
p2.textContent = text2.noCommitSelectedBody;
|
|
22872
|
+
const actions = deps.empty.querySelector(".empty-actions");
|
|
22873
|
+
if (actions)
|
|
22874
|
+
actions.hidden = true;
|
|
21908
22875
|
}
|
|
21909
22876
|
deps.setStatus("live");
|
|
21910
22877
|
}
|
|
@@ -21962,14 +22929,37 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
21962
22929
|
en: {
|
|
21963
22930
|
worktreeLabel: "Uncommitted changes (Working tree)",
|
|
21964
22931
|
bodyExpandClose: "Collapse",
|
|
21965
|
-
bodyExpandMore: (n2) => `Show more (${n2} lines)
|
|
22932
|
+
bodyExpandMore: (n2) => `Show more (${n2} lines)`,
|
|
22933
|
+
refreshLabel: "Refresh",
|
|
22934
|
+
refreshLabelPending: "Update",
|
|
22935
|
+
refreshTitle: "Refresh commit history",
|
|
22936
|
+
refreshTitlePending: "History may have changed. Refresh",
|
|
22937
|
+
refreshPendingStatus: "History may have changed",
|
|
22938
|
+
refreshResultUpdated: (sha) => `Updated: ${sha} is now latest`,
|
|
22939
|
+
refreshResultUnchanged: "No new commits",
|
|
22940
|
+
refreshResultUnchangedInView: "No new commits in this view",
|
|
22941
|
+
filterClearLabel: "Clear",
|
|
22942
|
+
filterClearTitle: "Clear commit filter"
|
|
21966
22943
|
},
|
|
21967
22944
|
ja: {
|
|
21968
22945
|
worktreeLabel: "未コミット変更 (Working tree)",
|
|
21969
22946
|
bodyExpandClose: "閉じる",
|
|
21970
|
-
bodyExpandMore: (n2) => `もっと見る (${n2} 行)
|
|
22947
|
+
bodyExpandMore: (n2) => `もっと見る (${n2} 行)`,
|
|
22948
|
+
refreshLabel: "更新",
|
|
22949
|
+
refreshLabelPending: "更新あり",
|
|
22950
|
+
refreshTitle: "コミット履歴を更新",
|
|
22951
|
+
refreshTitlePending: "新しい履歴がある可能性があります。更新",
|
|
22952
|
+
refreshPendingStatus: "新しい履歴がある可能性があります",
|
|
22953
|
+
refreshResultUpdated: (sha) => `更新: ${sha} が最新です`,
|
|
22954
|
+
refreshResultUnchanged: "新しいコミットはありません",
|
|
22955
|
+
refreshResultUnchangedInView: "この表示では新しいコミットはありません",
|
|
22956
|
+
filterClearLabel: "解除",
|
|
22957
|
+
filterClearTitle: "コミットフィルタを解除"
|
|
21971
22958
|
}
|
|
21972
22959
|
};
|
|
22960
|
+
function historyText(lang) {
|
|
22961
|
+
return HISTORY_TEXT[lang];
|
|
22962
|
+
}
|
|
21973
22963
|
function historyWorktreeLabel(lang) {
|
|
21974
22964
|
return HISTORY_TEXT[lang].worktreeLabel;
|
|
21975
22965
|
}
|
|
@@ -21990,6 +22980,20 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
21990
22980
|
title.className = "history-title";
|
|
21991
22981
|
title.textContent = "Commits";
|
|
21992
22982
|
panelHead.appendChild(title);
|
|
22983
|
+
const refreshButton = document.createElement("button");
|
|
22984
|
+
refreshButton.type = "button";
|
|
22985
|
+
refreshButton.className = "history-refresh";
|
|
22986
|
+
refreshButton.title = HISTORY_TEXT.en.refreshTitle;
|
|
22987
|
+
refreshButton.setAttribute("aria-label", HISTORY_TEXT.en.refreshTitle);
|
|
22988
|
+
refreshButton.innerHTML = iconSvg("octicon-sync", SYNC_16_PATH);
|
|
22989
|
+
const refreshLabel = document.createElement("span");
|
|
22990
|
+
refreshLabel.className = "history-refresh-label";
|
|
22991
|
+
refreshLabel.textContent = HISTORY_TEXT.en.refreshLabel;
|
|
22992
|
+
refreshButton.appendChild(refreshLabel);
|
|
22993
|
+
const refreshResult = document.createElement("span");
|
|
22994
|
+
refreshResult.className = "db-refresh-result history-refresh-result";
|
|
22995
|
+
refreshResult.setAttribute("aria-live", "polite");
|
|
22996
|
+
refreshResult.hidden = true;
|
|
21993
22997
|
if (page) {
|
|
21994
22998
|
const refMount = document.createElement("span");
|
|
21995
22999
|
refMount.dataset.refSelectorMount = "";
|
|
@@ -21998,6 +23002,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
21998
23002
|
refMount.dataset.title = "history ref";
|
|
21999
23003
|
panelHead.appendChild(refMount);
|
|
22000
23004
|
}
|
|
23005
|
+
panelHead.append(refreshButton, refreshResult);
|
|
22001
23006
|
const filterWrap = document.createElement("div");
|
|
22002
23007
|
filterWrap.className = "history-filter-wrap";
|
|
22003
23008
|
const filterInput = document.createElement("input");
|
|
@@ -22008,7 +23013,16 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22008
23013
|
filterInput.type = "search";
|
|
22009
23014
|
filterInput.placeholder = page ? "filter commits… (message, sha, author:name, path:file)" : "filter commits… (message, sha, author:name)";
|
|
22010
23015
|
filterInput.autocomplete = "off";
|
|
22011
|
-
|
|
23016
|
+
const filterClearButton = document.createElement("button");
|
|
23017
|
+
filterClearButton.type = "button";
|
|
23018
|
+
if (page)
|
|
23019
|
+
filterClearButton.id = "history-filter-clear";
|
|
23020
|
+
filterClearButton.className = "history-filter-clear";
|
|
23021
|
+
filterClearButton.hidden = true;
|
|
23022
|
+
filterClearButton.textContent = HISTORY_TEXT.en.filterClearLabel;
|
|
23023
|
+
filterClearButton.title = HISTORY_TEXT.en.filterClearTitle;
|
|
23024
|
+
filterClearButton.setAttribute("aria-label", HISTORY_TEXT.en.filterClearTitle);
|
|
23025
|
+
filterWrap.append(filterInput, filterClearButton);
|
|
22012
23026
|
const banner = document.createElement("div");
|
|
22013
23027
|
if (page)
|
|
22014
23028
|
banner.id = "history-banner";
|
|
@@ -22031,7 +23045,17 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22031
23045
|
status.hidden = true;
|
|
22032
23046
|
status.setAttribute("role", "status");
|
|
22033
23047
|
panel.append(panelHead, filterWrap, banner, list2, sentinel, status);
|
|
22034
|
-
return {
|
|
23048
|
+
return {
|
|
23049
|
+
panel,
|
|
23050
|
+
list: list2,
|
|
23051
|
+
banner,
|
|
23052
|
+
status,
|
|
23053
|
+
sentinel,
|
|
23054
|
+
filterInput,
|
|
23055
|
+
filterClearButton,
|
|
23056
|
+
refreshButton,
|
|
23057
|
+
refreshResult
|
|
23058
|
+
};
|
|
22035
23059
|
}
|
|
22036
23060
|
function buildHistoryCommitInfoDom(options = {}) {
|
|
22037
23061
|
const variant = options.variant || "page";
|
|
@@ -22129,6 +23153,9 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22129
23153
|
status: deps.$("#history-status"),
|
|
22130
23154
|
sentinel: deps.$("#history-sentinel"),
|
|
22131
23155
|
filterInput: document.querySelector("#history-filter"),
|
|
23156
|
+
filterClearButton: document.querySelector("#history-filter-clear"),
|
|
23157
|
+
refreshButton: document.querySelector(".history-refresh"),
|
|
23158
|
+
refreshResult: document.querySelector(".history-refresh-result"),
|
|
22132
23159
|
commitInfo: document.querySelector("#history-commit-info")
|
|
22133
23160
|
};
|
|
22134
23161
|
let activeMount = defaultMount;
|
|
@@ -22139,6 +23166,8 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22139
23166
|
let sentinel = defaultMount.sentinel;
|
|
22140
23167
|
let attachedList = null;
|
|
22141
23168
|
let attachedFilterInput = null;
|
|
23169
|
+
let attachedFilterClearButton = null;
|
|
23170
|
+
let attachedRefreshButton = null;
|
|
22142
23171
|
let filterTimer = null;
|
|
22143
23172
|
let observer = null;
|
|
22144
23173
|
let ref = "HEAD";
|
|
@@ -22152,6 +23181,8 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22152
23181
|
let mode = "history";
|
|
22153
23182
|
let routeRef = "HEAD";
|
|
22154
23183
|
let pathFilter = "";
|
|
23184
|
+
let refreshStatus = { type: "none" };
|
|
23185
|
+
let freshSha = "";
|
|
22155
23186
|
function historyScopeFromRoute(route = deps.getRoute()) {
|
|
22156
23187
|
if (route.screen === "history") {
|
|
22157
23188
|
const nextRef = route.ref || "HEAD";
|
|
@@ -22175,6 +23206,18 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22175
23206
|
}
|
|
22176
23207
|
return null;
|
|
22177
23208
|
}
|
|
23209
|
+
function currentRefreshScopeKey() {
|
|
23210
|
+
const scope = historyScopeFromRoute();
|
|
23211
|
+
if (!scope)
|
|
23212
|
+
return "";
|
|
23213
|
+
return [
|
|
23214
|
+
scope.mode,
|
|
23215
|
+
scope.logRef,
|
|
23216
|
+
scope.routeRef,
|
|
23217
|
+
scope.pathFilter,
|
|
23218
|
+
query
|
|
23219
|
+
].join("\x00");
|
|
23220
|
+
}
|
|
22178
23221
|
function worktreeDiffRange() {
|
|
22179
23222
|
return { from: "HEAD", to: "worktree" };
|
|
22180
23223
|
}
|
|
@@ -22186,6 +23229,39 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22186
23229
|
statusEl.textContent = message;
|
|
22187
23230
|
statusEl.hidden = !message;
|
|
22188
23231
|
}
|
|
23232
|
+
function latestCommitSha() {
|
|
23233
|
+
return commits.find((commit) => commit.sha !== HISTORY_WORKTREE_COMMIT)?.sha || "";
|
|
23234
|
+
}
|
|
23235
|
+
function clearRefreshResult() {
|
|
23236
|
+
refreshStatus = { type: "none" };
|
|
23237
|
+
freshSha = "";
|
|
23238
|
+
syncRefreshResult();
|
|
23239
|
+
}
|
|
23240
|
+
function setRefreshResult(previousTopSha, nextTopSha) {
|
|
23241
|
+
freshSha = previousTopSha && nextTopSha && previousTopSha !== nextTopSha ? nextTopSha : "";
|
|
23242
|
+
refreshStatus = freshSha ? { type: "updated", sha: nextTopSha.slice(0, 7) } : { type: "unchanged", scoped: Boolean(query || pathFilter) };
|
|
23243
|
+
renderList();
|
|
23244
|
+
}
|
|
23245
|
+
function refreshStatusMessage() {
|
|
23246
|
+
const text2 = historyText(deps.getLanguage());
|
|
23247
|
+
switch (refreshStatus.type) {
|
|
23248
|
+
case "pending":
|
|
23249
|
+
return text2.refreshPendingStatus;
|
|
23250
|
+
case "updated":
|
|
23251
|
+
return text2.refreshResultUpdated(refreshStatus.sha);
|
|
23252
|
+
case "unchanged":
|
|
23253
|
+
return refreshStatus.scoped ? text2.refreshResultUnchangedInView : text2.refreshResultUnchanged;
|
|
23254
|
+
case "none":
|
|
23255
|
+
return "";
|
|
23256
|
+
default: {
|
|
23257
|
+
const exhaustive = refreshStatus;
|
|
23258
|
+
return exhaustive;
|
|
23259
|
+
}
|
|
23260
|
+
}
|
|
23261
|
+
}
|
|
23262
|
+
function syncRefreshStatusText() {
|
|
23263
|
+
setStatusText(loading ? "loading..." : refreshStatusMessage() || (commits.length ? "" : "no commits"));
|
|
23264
|
+
}
|
|
22189
23265
|
function commitInfoElement() {
|
|
22190
23266
|
return activeMount.commitInfo || document.querySelector("#history-commit-info");
|
|
22191
23267
|
}
|
|
@@ -22257,13 +23333,16 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22257
23333
|
}
|
|
22258
23334
|
function commitRow(commit) {
|
|
22259
23335
|
const active = commit.sha === selectedSha ? " active" : "";
|
|
22260
|
-
|
|
23336
|
+
const fresh = commit.sha === freshSha ? " history-item-fresh" : "";
|
|
23337
|
+
return `<li class="history-item${active}${fresh}" data-sha="${deps.escapeHtml(commit.sha)}">` + `<span class="subject" title="${deps.escapeHtml(commit.subject)}">${deps.escapeHtml(commit.subject)}</span>` + `<span class="meta2">` + `<span class="sha">${deps.escapeHtml(commit.sha.slice(0, 7))}</span>` + `<span class="author">${deps.escapeHtml(commit.author)}</span>` + `<span class="when">${deps.escapeHtml(displayWhen(commit.when))}</span>` + `</span>` + `</li>`;
|
|
22261
23338
|
}
|
|
22262
23339
|
function worktreeRow() {
|
|
22263
23340
|
const active = selectedSha === HISTORY_WORKTREE_COMMIT ? " active" : "";
|
|
22264
23341
|
return `<li class="history-item history-item-worktree${active}" data-sha="${HISTORY_WORKTREE_COMMIT}">` + `<span class="subject" title="${deps.escapeHtml(historyWorktreeLabel(deps.getLanguage()))}">${deps.escapeHtml(historyWorktreeLabel(deps.getLanguage()))}</span>` + `<span class="meta2">` + `<span class="sha">HEAD..worktree</span>` + `<span class="author">Working tree</span>` + `</span>` + `</li>`;
|
|
22265
23342
|
}
|
|
22266
23343
|
function renderList() {
|
|
23344
|
+
syncRefreshButton(activeMount.refreshButton);
|
|
23345
|
+
syncRefreshResult(activeMount.refreshResult);
|
|
22267
23346
|
const now = new Date;
|
|
22268
23347
|
const html = mode === "history" ? [worktreeRow()] : [];
|
|
22269
23348
|
let lastGroup = "";
|
|
@@ -22280,7 +23359,42 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22280
23359
|
html.push(commitRow(commit));
|
|
22281
23360
|
}
|
|
22282
23361
|
list2.innerHTML = html.join("");
|
|
22283
|
-
|
|
23362
|
+
syncRefreshStatusText();
|
|
23363
|
+
}
|
|
23364
|
+
function syncRefreshButton(button) {
|
|
23365
|
+
if (!button)
|
|
23366
|
+
return;
|
|
23367
|
+
const text2 = historyText(deps.getLanguage());
|
|
23368
|
+
const hasPendingUpdate = refreshStatus.type === "pending";
|
|
23369
|
+
const title = hasPendingUpdate ? text2.refreshTitlePending : text2.refreshTitle;
|
|
23370
|
+
button.title = title;
|
|
23371
|
+
button.setAttribute("aria-label", title);
|
|
23372
|
+
button.classList.toggle("has-update", hasPendingUpdate);
|
|
23373
|
+
const label = button.querySelector(".history-refresh-label");
|
|
23374
|
+
if (label) {
|
|
23375
|
+
label.textContent = hasPendingUpdate ? text2.refreshLabelPending : text2.refreshLabel;
|
|
23376
|
+
}
|
|
23377
|
+
}
|
|
23378
|
+
function syncRefreshResult(result) {
|
|
23379
|
+
const el = result ?? activeMount.refreshResult;
|
|
23380
|
+
if (!el)
|
|
23381
|
+
return;
|
|
23382
|
+
const message = refreshStatus.type === "pending" || refreshStatus.type === "updated" || refreshStatus.type === "unchanged" ? refreshStatusMessage() : "";
|
|
23383
|
+
el.textContent = message;
|
|
23384
|
+
el.hidden = message.length === 0;
|
|
23385
|
+
el.classList.toggle("changed", refreshStatus.type === "updated");
|
|
23386
|
+
el.classList.toggle("pending", refreshStatus.type === "pending");
|
|
23387
|
+
}
|
|
23388
|
+
function syncFilterClearButton(button) {
|
|
23389
|
+
const clearButton = button ?? activeMount.filterClearButton;
|
|
23390
|
+
if (!clearButton)
|
|
23391
|
+
return;
|
|
23392
|
+
const input = activeMount.filterInput ?? null;
|
|
23393
|
+
const text2 = historyText(deps.getLanguage());
|
|
23394
|
+
clearButton.textContent = text2.filterClearLabel;
|
|
23395
|
+
clearButton.title = text2.filterClearTitle;
|
|
23396
|
+
clearButton.setAttribute("aria-label", text2.filterClearTitle);
|
|
23397
|
+
clearButton.hidden = !(input?.value || "");
|
|
22284
23398
|
}
|
|
22285
23399
|
async function updateCommitInfo(commit) {
|
|
22286
23400
|
const info = commitInfoElement();
|
|
@@ -22559,6 +23673,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22559
23673
|
selectionGeneration++;
|
|
22560
23674
|
selectedSha = "";
|
|
22561
23675
|
setBanner("");
|
|
23676
|
+
clearRefreshResult();
|
|
22562
23677
|
await updateCommitInfo(null);
|
|
22563
23678
|
renderList();
|
|
22564
23679
|
await loadNextPage();
|
|
@@ -22629,6 +23744,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22629
23744
|
query = value;
|
|
22630
23745
|
generation++;
|
|
22631
23746
|
selectionGeneration++;
|
|
23747
|
+
clearRefreshResult();
|
|
22632
23748
|
commits = [];
|
|
22633
23749
|
hasMore = false;
|
|
22634
23750
|
loading = false;
|
|
@@ -22648,6 +23764,7 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22648
23764
|
const input = activeFilterInputFromEvent(event);
|
|
22649
23765
|
if (!input)
|
|
22650
23766
|
return;
|
|
23767
|
+
syncFilterClearButton();
|
|
22651
23768
|
if (filterTimer)
|
|
22652
23769
|
clearTimeout(filterTimer);
|
|
22653
23770
|
filterTimer = setTimeout(() => {
|
|
@@ -22663,13 +23780,54 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22663
23780
|
return;
|
|
22664
23781
|
if (e2.key === "Escape" && input.value) {
|
|
22665
23782
|
input.value = "";
|
|
23783
|
+
syncFilterClearButton();
|
|
22666
23784
|
applyFilter("");
|
|
22667
23785
|
e2.stopPropagation();
|
|
22668
23786
|
}
|
|
22669
23787
|
}
|
|
23788
|
+
function handleFilterClearClick() {
|
|
23789
|
+
const input = attachedFilterInput;
|
|
23790
|
+
if (!input?.value)
|
|
23791
|
+
return;
|
|
23792
|
+
if (filterTimer) {
|
|
23793
|
+
clearTimeout(filterTimer);
|
|
23794
|
+
filterTimer = null;
|
|
23795
|
+
}
|
|
23796
|
+
input.value = "";
|
|
23797
|
+
syncFilterClearButton();
|
|
23798
|
+
applyFilter("");
|
|
23799
|
+
input.focus?.();
|
|
23800
|
+
}
|
|
23801
|
+
async function handleRefreshClick() {
|
|
23802
|
+
const button = attachedRefreshButton;
|
|
23803
|
+
if (button?.disabled)
|
|
23804
|
+
return;
|
|
23805
|
+
const refreshScopeKey = currentRefreshScopeKey();
|
|
23806
|
+
const previousTopSha = latestCommitSha();
|
|
23807
|
+
clearRefreshResult();
|
|
23808
|
+
if (button) {
|
|
23809
|
+
button.disabled = true;
|
|
23810
|
+
button.classList.add("spinning");
|
|
23811
|
+
}
|
|
23812
|
+
try {
|
|
23813
|
+
await enterHistory({ mount: activeMount, force: true });
|
|
23814
|
+
if (!refreshScopeKey || currentRefreshScopeKey() !== refreshScopeKey)
|
|
23815
|
+
return;
|
|
23816
|
+
setRefreshResult(previousTopSha, latestCommitSha());
|
|
23817
|
+
} finally {
|
|
23818
|
+
if (button) {
|
|
23819
|
+
button.classList.remove("spinning");
|
|
23820
|
+
button.disabled = false;
|
|
23821
|
+
}
|
|
23822
|
+
}
|
|
23823
|
+
}
|
|
22670
23824
|
function activateMount(mount) {
|
|
22671
|
-
if (activeMount === mount && attachedList === mount.list)
|
|
23825
|
+
if (activeMount === mount && attachedList === mount.list) {
|
|
23826
|
+
syncRefreshButton(mount.refreshButton);
|
|
23827
|
+
syncRefreshResult(mount.refreshResult);
|
|
23828
|
+
syncFilterClearButton(mount.filterClearButton);
|
|
22672
23829
|
return;
|
|
23830
|
+
}
|
|
22673
23831
|
if (attachedList) {
|
|
22674
23832
|
attachedList.removeEventListener("click", handleListClick);
|
|
22675
23833
|
attachedList = null;
|
|
@@ -22680,6 +23838,14 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22680
23838
|
attachedFilterInput.removeEventListener("keydown", handleFilterKeydown);
|
|
22681
23839
|
attachedFilterInput = null;
|
|
22682
23840
|
}
|
|
23841
|
+
if (attachedFilterClearButton) {
|
|
23842
|
+
attachedFilterClearButton.removeEventListener("click", handleFilterClearClick);
|
|
23843
|
+
attachedFilterClearButton = null;
|
|
23844
|
+
}
|
|
23845
|
+
if (attachedRefreshButton) {
|
|
23846
|
+
attachedRefreshButton.removeEventListener("click", handleRefreshClick);
|
|
23847
|
+
attachedRefreshButton = null;
|
|
23848
|
+
}
|
|
22683
23849
|
if (filterTimer) {
|
|
22684
23850
|
clearTimeout(filterTimer);
|
|
22685
23851
|
filterTimer = null;
|
|
@@ -22701,6 +23867,19 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22701
23867
|
input.addEventListener("keydown", handleFilterKeydown);
|
|
22702
23868
|
attachedFilterInput = input;
|
|
22703
23869
|
}
|
|
23870
|
+
const filterClearButton = mount.filterClearButton ?? null;
|
|
23871
|
+
if (filterClearButton) {
|
|
23872
|
+
syncFilterClearButton(filterClearButton);
|
|
23873
|
+
filterClearButton.addEventListener("click", handleFilterClearClick);
|
|
23874
|
+
attachedFilterClearButton = filterClearButton;
|
|
23875
|
+
}
|
|
23876
|
+
const refreshButton = mount.refreshButton ?? null;
|
|
23877
|
+
if (refreshButton) {
|
|
23878
|
+
syncRefreshButton(refreshButton);
|
|
23879
|
+
syncRefreshResult(mount.refreshResult);
|
|
23880
|
+
refreshButton.addEventListener("click", handleRefreshClick);
|
|
23881
|
+
attachedRefreshButton = refreshButton;
|
|
23882
|
+
}
|
|
22704
23883
|
observer = new IntersectionObserver((entries) => {
|
|
22705
23884
|
if (!entries.some((entry) => entry.isIntersecting))
|
|
22706
23885
|
return;
|
|
@@ -22737,6 +23916,18 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22737
23916
|
enterHistory,
|
|
22738
23917
|
leaveHistory,
|
|
22739
23918
|
onRefPicked,
|
|
23919
|
+
localize: () => {
|
|
23920
|
+
syncRefreshButton(activeMount.refreshButton);
|
|
23921
|
+
syncRefreshResult(activeMount.refreshResult);
|
|
23922
|
+
syncFilterClearButton(activeMount.filterClearButton);
|
|
23923
|
+
renderList();
|
|
23924
|
+
},
|
|
23925
|
+
notePossibleUpdate: () => {
|
|
23926
|
+
refreshStatus = { type: "pending" };
|
|
23927
|
+
syncRefreshButton(activeMount.refreshButton);
|
|
23928
|
+
syncRefreshResult(activeMount.refreshResult);
|
|
23929
|
+
syncRefreshStatusText();
|
|
23930
|
+
},
|
|
22740
23931
|
isWorktreeSelected: () => selectedSha === HISTORY_WORKTREE_COMMIT
|
|
22741
23932
|
};
|
|
22742
23933
|
}
|
|
@@ -22765,15 +23956,16 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22765
23956
|
const diffPane = document.createElement("main");
|
|
22766
23957
|
diffPane.className = "gdp-file-history-diff-pane";
|
|
22767
23958
|
const commitInfo = buildHistoryCommitInfoDom({ variant: "file" });
|
|
23959
|
+
const emptyText = deps.emptyText();
|
|
22768
23960
|
const empty = document.createElement("div");
|
|
22769
23961
|
empty.className = "empty gdp-file-history-empty hidden";
|
|
22770
23962
|
const emptyIcon = document.createElement("div");
|
|
22771
|
-
emptyIcon.className = "
|
|
22772
|
-
emptyIcon.
|
|
23963
|
+
emptyIcon.className = "empty-icon";
|
|
23964
|
+
emptyIcon.innerHTML = iconSvg("octicon-git-branch", GIT_BRANCH_16_PATH);
|
|
22773
23965
|
const emptyTitle = document.createElement("h2");
|
|
22774
|
-
emptyTitle.textContent =
|
|
23966
|
+
emptyTitle.textContent = emptyText.noCommitSelectedTitle;
|
|
22775
23967
|
const emptyBody = document.createElement("p");
|
|
22776
|
-
emptyBody.textContent =
|
|
23968
|
+
emptyBody.textContent = emptyText.noCommitSelectedBody;
|
|
22777
23969
|
empty.append(emptyIcon, emptyTitle, emptyBody);
|
|
22778
23970
|
const diffHost = document.createElement("div");
|
|
22779
23971
|
diffHost.className = "gdp-file-history-diff";
|
|
@@ -22823,8 +24015,8 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22823
24015
|
{
|
|
22824
24016
|
selectors: [{ action: "open-help" }],
|
|
22825
24017
|
description: {
|
|
22826
|
-
en: "Open
|
|
22827
|
-
ja: "
|
|
24018
|
+
en: "Open quick help",
|
|
24019
|
+
ja: "クイックヘルプを開く"
|
|
22828
24020
|
}
|
|
22829
24021
|
},
|
|
22830
24022
|
{
|
|
@@ -22851,6 +24043,13 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
22851
24043
|
ja: "前 / 次の注釈へ移動"
|
|
22852
24044
|
}
|
|
22853
24045
|
},
|
|
24046
|
+
{
|
|
24047
|
+
selectors: [{ action: "next-unviewed-file" }],
|
|
24048
|
+
description: {
|
|
24049
|
+
en: "Jump to the next unviewed file",
|
|
24050
|
+
ja: "次の未確認ファイルへ移動"
|
|
24051
|
+
}
|
|
24052
|
+
},
|
|
22854
24053
|
{
|
|
22855
24054
|
selectors: [{ action: "layout-unified" }, { action: "layout-split" }],
|
|
22856
24055
|
description: {
|
|
@@ -23096,8 +24295,9 @@ ${entry.message}` : entry.detail ?? entry.message ?? "";
|
|
|
23096
24295
|
addUnique(labels, item.label);
|
|
23097
24296
|
return [labels.join(" / "), row.description[language]];
|
|
23098
24297
|
}
|
|
23099
|
-
function buildHelpKeybindingGroups(language, bindings = DEFAULT_KEY_BINDINGS) {
|
|
23100
|
-
|
|
24298
|
+
function buildHelpKeybindingGroups(language, bindings = DEFAULT_KEY_BINDINGS, onlyTitlesEn) {
|
|
24299
|
+
const groups = onlyTitlesEn ? HELP_KEYBINDING_GROUPS.filter((group) => onlyTitlesEn.includes(group.title.en)) : HELP_KEYBINDING_GROUPS;
|
|
24300
|
+
return groups.map((group) => ({
|
|
23101
24301
|
title: group.title[language],
|
|
23102
24302
|
rows: group.rows.map((row) => buildRow(row, language, bindings))
|
|
23103
24303
|
}));
|
|
@@ -23469,7 +24669,7 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
23469
24669
|
],
|
|
23470
24670
|
[
|
|
23471
24671
|
"Data tab",
|
|
23472
|
-
"Paginated grid with sort, filter, cell copy,
|
|
24672
|
+
"Paginated grid with sort, filter, cell copy, CSV/JSON export (capped at 100k rows; export respects the current filter and sort), and a table-only reload action that keeps global search and column filters. Reload results are announced beside the button so row-count changes are visible. Toggle Edit mode in the prefs bar to enable inline editing — double-click a cell to edit, queue insert/delete via row actions, and commit the batch atomically. Edited rows/cells highlight in yellow until committed."
|
|
23473
24673
|
],
|
|
23474
24674
|
[
|
|
23475
24675
|
"Detail footer & related panel",
|
|
@@ -23477,7 +24677,7 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
23477
24677
|
],
|
|
23478
24678
|
[
|
|
23479
24679
|
"Schema tab",
|
|
23480
|
-
"Column definitions, indexes, foreign keys, triggers, and DDL."
|
|
24680
|
+
"Column definitions, indexes, foreign keys, triggers, and DDL, with an in-tab refresh action for reloading the current table structure."
|
|
23481
24681
|
],
|
|
23482
24682
|
[
|
|
23483
24683
|
"Query editor",
|
|
@@ -24121,7 +25321,7 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
24121
25321
|
],
|
|
24122
25322
|
[
|
|
24123
25323
|
"Data タブ",
|
|
24124
|
-
"ページネーション付きグリッド。ソート、フィルター、セルコピー、CSV/JSON エクスポート(最大10
|
|
25324
|
+
"ページネーション付きグリッド。ソート、フィルター、セルコピー、CSV/JSON エクスポート(最大10万行、現在のフィルター/ソートを反映)、全体検索と列フィルターを保持した表だけの再読み込みに対応。再読み込み結果はボタン横に表示され、行数変化に気づけます。設定バーで Edit モードを ON にするとインライン編集が可能 — セルをダブルクリックで編集、行操作で挿入/削除を予約、コミット単位で一括適用。未コミットの編集行/セルは黄色でハイライト。"
|
|
24125
25325
|
],
|
|
24126
25326
|
[
|
|
24127
25327
|
"詳細フッタ・関連パネル",
|
|
@@ -24129,7 +25329,7 @@ code-viewer annotate add-db --db app.db --tab query \\
|
|
|
24129
25329
|
],
|
|
24130
25330
|
[
|
|
24131
25331
|
"Schema タブ",
|
|
24132
|
-
"カラム定義、インデックス、外部キー、トリガー、DDL
|
|
25332
|
+
"カラム定義、インデックス、外部キー、トリガー、DDL。現在の表構造だけを再読み込みするタブ内更新にも対応。"
|
|
24133
25333
|
],
|
|
24134
25334
|
[
|
|
24135
25335
|
"クエリエディター",
|
|
@@ -24801,6 +26001,7 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
24801
26001
|
const button = document.createElement("button");
|
|
24802
26002
|
button.className = "gdp-expand-btn";
|
|
24803
26003
|
button.title = spec.title;
|
|
26004
|
+
button.setAttribute("aria-label", spec.title);
|
|
24804
26005
|
button.innerHTML = '<svg viewBox="0 0 16 16" width="12" height="12" aria-hidden="true">' + '<path fill="currentColor" d="' + EXPAND_ICON_PATHS[spec.direction] + '"/></svg>';
|
|
24805
26006
|
button.addEventListener("click", (e2) => {
|
|
24806
26007
|
e2.stopPropagation();
|
|
@@ -25139,6 +26340,86 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
25139
26340
|
};
|
|
25140
26341
|
}
|
|
25141
26342
|
|
|
26343
|
+
// web-src/views/quick-help.ts
|
|
26344
|
+
var QUICK_HELP_GROUP_TITLES_EN = ["Global", "Main Panel"];
|
|
26345
|
+
function createQuickHelp(deps) {
|
|
26346
|
+
const popover = deps.$("#quick-help-popover");
|
|
26347
|
+
const trigger = deps.$("#quick-help-btn");
|
|
26348
|
+
const titleEl = deps.$("#quick-help-title");
|
|
26349
|
+
const closeBtn = deps.$("#quick-help-close");
|
|
26350
|
+
const groupsHost = deps.$("#quick-help-groups");
|
|
26351
|
+
const fullLink = deps.$("#quick-help-full-link");
|
|
26352
|
+
function isOpen() {
|
|
26353
|
+
return !popover.hidden;
|
|
26354
|
+
}
|
|
26355
|
+
function renderContent() {
|
|
26356
|
+
groupsHost.innerHTML = "";
|
|
26357
|
+
const groups = buildHelpKeybindingGroups(deps.getLanguage(), undefined, QUICK_HELP_GROUP_TITLES_EN);
|
|
26358
|
+
for (const group of groups) {
|
|
26359
|
+
const section = document.createElement("section");
|
|
26360
|
+
section.className = "gdp-help-group";
|
|
26361
|
+
const title = document.createElement("h3");
|
|
26362
|
+
title.textContent = group.title;
|
|
26363
|
+
section.append(title, renderHelpTable(group.rows));
|
|
26364
|
+
groupsHost.appendChild(section);
|
|
26365
|
+
}
|
|
26366
|
+
}
|
|
26367
|
+
function applyText() {
|
|
26368
|
+
const text2 = deps.getText();
|
|
26369
|
+
titleEl.textContent = text2.panelTitle;
|
|
26370
|
+
popover.setAttribute("aria-label", text2.panelTitle);
|
|
26371
|
+
closeBtn.setAttribute("aria-label", text2.close);
|
|
26372
|
+
fullLink.textContent = text2.viewAll;
|
|
26373
|
+
}
|
|
26374
|
+
function open() {
|
|
26375
|
+
applyText();
|
|
26376
|
+
renderContent();
|
|
26377
|
+
popover.hidden = false;
|
|
26378
|
+
closeBtn.focus();
|
|
26379
|
+
}
|
|
26380
|
+
function close() {
|
|
26381
|
+
if (!isOpen())
|
|
26382
|
+
return;
|
|
26383
|
+
popover.hidden = true;
|
|
26384
|
+
}
|
|
26385
|
+
function toggle() {
|
|
26386
|
+
if (isOpen())
|
|
26387
|
+
close();
|
|
26388
|
+
else
|
|
26389
|
+
open();
|
|
26390
|
+
}
|
|
26391
|
+
trigger.addEventListener("click", toggle);
|
|
26392
|
+
closeBtn.addEventListener("click", close);
|
|
26393
|
+
fullLink.addEventListener("click", (e2) => {
|
|
26394
|
+
e2.preventDefault();
|
|
26395
|
+
close();
|
|
26396
|
+
deps.openFullKeybindings();
|
|
26397
|
+
});
|
|
26398
|
+
document.addEventListener("keydown", (e2) => {
|
|
26399
|
+
if (isImeComposing(e2))
|
|
26400
|
+
return;
|
|
26401
|
+
if (e2.key !== "Escape")
|
|
26402
|
+
return;
|
|
26403
|
+
if (!isOpen())
|
|
26404
|
+
return;
|
|
26405
|
+
close();
|
|
26406
|
+
});
|
|
26407
|
+
document.addEventListener("mousedown", (e2) => {
|
|
26408
|
+
if (!isOpen())
|
|
26409
|
+
return;
|
|
26410
|
+
const target = e2.target;
|
|
26411
|
+
if (popover.contains(target) || trigger.contains(target))
|
|
26412
|
+
return;
|
|
26413
|
+
close();
|
|
26414
|
+
});
|
|
26415
|
+
function localize() {
|
|
26416
|
+
applyText();
|
|
26417
|
+
if (isOpen())
|
|
26418
|
+
renderContent();
|
|
26419
|
+
}
|
|
26420
|
+
return { open, close, toggle, isOpen, localize };
|
|
26421
|
+
}
|
|
26422
|
+
|
|
25142
26423
|
// web-src/views/ref-picker.ts
|
|
25143
26424
|
function createRefPicker(deps) {
|
|
25144
26425
|
function wireRefSelectorInput(input, onPick) {
|
|
@@ -25570,7 +26851,11 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
25570
26851
|
trackLoad,
|
|
25571
26852
|
getRepoSidebarRef,
|
|
25572
26853
|
setRepoSidebarRef,
|
|
25573
|
-
isTestPath
|
|
26854
|
+
isTestPath,
|
|
26855
|
+
sidebarToggleTitle,
|
|
26856
|
+
openDirectoryInOsTitle,
|
|
26857
|
+
omittedDirectoryBadge,
|
|
26858
|
+
commitEntryBadge
|
|
25574
26859
|
} = deps;
|
|
25575
26860
|
const VIRTUAL_SIDEBAR_THRESHOLD = 3000;
|
|
25576
26861
|
const VIRTUAL_SIDEBAR_ROW_HEIGHT = 29;
|
|
@@ -25647,8 +26932,9 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
25647
26932
|
button = createSidebarToggleButton();
|
|
25648
26933
|
bindSidebarToggleButton(button);
|
|
25649
26934
|
button.setAttribute("aria-pressed", STATE.sidebarHidden ? "true" : "false");
|
|
25650
|
-
|
|
25651
|
-
button.
|
|
26935
|
+
const toggleTitle = sidebarToggleTitle(STATE.sidebarHidden);
|
|
26936
|
+
button.title = toggleTitle;
|
|
26937
|
+
button.setAttribute("aria-label", toggleTitle);
|
|
25652
26938
|
syncSidebarToggleIcon(button);
|
|
25653
26939
|
return button;
|
|
25654
26940
|
}
|
|
@@ -25813,12 +27099,13 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
25813
27099
|
if (dir.children_omitted) {
|
|
25814
27100
|
const omitted = document.createElement("span");
|
|
25815
27101
|
omitted.className = "dir-omitted " + (dir.children_omitted_reason === "heavy" ? "dir-omitted-heavy" : "dir-omitted-internal");
|
|
25816
|
-
|
|
25817
|
-
omitted.
|
|
27102
|
+
const badge = omittedDirectoryBadge(dir.children_omitted_reason);
|
|
27103
|
+
omitted.textContent = badge.label;
|
|
27104
|
+
omitted.title = badge.title;
|
|
25818
27105
|
label.appendChild(omitted);
|
|
25819
27106
|
}
|
|
25820
27107
|
li.appendChild(label);
|
|
25821
|
-
li.appendChild(createOpenPathButton(dir.path, "directory",
|
|
27108
|
+
li.appendChild(createOpenPathButton(dir.path, "directory", openDirectoryInOsTitle()));
|
|
25822
27109
|
const collapsed = STATE.collapsedDirs.has(dir.path);
|
|
25823
27110
|
if (collapsed)
|
|
25824
27111
|
li.classList.add("collapsed");
|
|
@@ -25866,40 +27153,7 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
25866
27153
|
ul.appendChild(childUl);
|
|
25867
27154
|
} else {
|
|
25868
27155
|
const f2 = item.file;
|
|
25869
|
-
const li =
|
|
25870
|
-
li.className = "tree-file";
|
|
25871
|
-
li.tabIndex = -1;
|
|
25872
|
-
li.dataset.path = f2.path;
|
|
25873
|
-
li.dataset.type = "blob";
|
|
25874
|
-
li.classList.toggle("viewed", !onFileClick && STATE.viewedFiles.has(f2.path));
|
|
25875
|
-
li.style.setProperty("--lvl-pad", `${12 + depth * 14}px`);
|
|
25876
|
-
const spacer = document.createElement("span");
|
|
25877
|
-
spacer.className = "chev-spacer";
|
|
25878
|
-
li.appendChild(spacer);
|
|
25879
|
-
if (f2.status) {
|
|
25880
|
-
li.appendChild(fileBadge(f2.status));
|
|
25881
|
-
} else {
|
|
25882
|
-
const icon = document.createElement("span");
|
|
25883
|
-
icon.className = "d2h-icon-wrapper";
|
|
25884
|
-
icon.innerHTML = fileEntryIcon();
|
|
25885
|
-
li.appendChild(icon);
|
|
25886
|
-
}
|
|
25887
|
-
const name = document.createElement("span");
|
|
25888
|
-
name.className = "name";
|
|
25889
|
-
name.textContent = f2.path.split("/").pop();
|
|
25890
|
-
name.title = f2.path;
|
|
25891
|
-
li.appendChild(name);
|
|
25892
|
-
li.addEventListener("click", () => {
|
|
25893
|
-
if (onFileClick)
|
|
25894
|
-
onFileClick(f2);
|
|
25895
|
-
else
|
|
25896
|
-
scrollToFile(f2.path);
|
|
25897
|
-
scheduleMainSurfaceFocus();
|
|
25898
|
-
});
|
|
25899
|
-
if (!onFileClick)
|
|
25900
|
-
li.addEventListener("mouseenter", () => prefetchByPath(f2.path), {
|
|
25901
|
-
passive: true
|
|
25902
|
-
});
|
|
27156
|
+
const li = createTreeFileRow(f2, depth, onFileClick);
|
|
25903
27157
|
ul.appendChild(li);
|
|
25904
27158
|
}
|
|
25905
27159
|
}
|
|
@@ -25983,7 +27237,8 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
25983
27237
|
order: dir.minOrder + (index + 1) / 1e5,
|
|
25984
27238
|
path: entry.path,
|
|
25985
27239
|
display_path: entry.path,
|
|
25986
|
-
type: entry.type,
|
|
27240
|
+
type: meta.ref === "worktree" && entry.type === "commit" && !entry.submodule ? "tree" : entry.type,
|
|
27241
|
+
submodule: entry.submodule,
|
|
25987
27242
|
children_omitted: entry.children_omitted,
|
|
25988
27243
|
children_omitted_reason: entry.children_omitted_reason
|
|
25989
27244
|
}));
|
|
@@ -26033,12 +27288,13 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
26033
27288
|
if (dir.children_omitted) {
|
|
26034
27289
|
const omitted = document.createElement("span");
|
|
26035
27290
|
omitted.className = "dir-omitted " + (dir.children_omitted_reason === "heavy" ? "dir-omitted-heavy" : "dir-omitted-internal");
|
|
26036
|
-
|
|
26037
|
-
omitted.
|
|
27291
|
+
const badge = omittedDirectoryBadge(dir.children_omitted_reason);
|
|
27292
|
+
omitted.textContent = badge.label;
|
|
27293
|
+
omitted.title = badge.title;
|
|
26038
27294
|
label.appendChild(omitted);
|
|
26039
27295
|
}
|
|
26040
27296
|
li.appendChild(label);
|
|
26041
|
-
li.appendChild(createOpenPathButton(dir.path, "directory",
|
|
27297
|
+
li.appendChild(createOpenPathButton(dir.path, "directory", openDirectoryInOsTitle()));
|
|
26042
27298
|
const updateIcon = () => {
|
|
26043
27299
|
setFolderIcon(dirIcon, li.classList.contains("collapsed"));
|
|
26044
27300
|
};
|
|
@@ -26104,12 +27360,37 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
26104
27360
|
}
|
|
26105
27361
|
return li;
|
|
26106
27362
|
}
|
|
27363
|
+
function fileKindTag(f2) {
|
|
27364
|
+
if (f2.type === "commit") {
|
|
27365
|
+
const badge = commitEntryBadge(f2.submodule);
|
|
27366
|
+
const tag2 = document.createElement("span");
|
|
27367
|
+
tag2.className = `kind-tag ${f2.submodule ? "submodule" : "gitlink"}`;
|
|
27368
|
+
tag2.textContent = badge.label;
|
|
27369
|
+
tag2.title = badge.title;
|
|
27370
|
+
return tag2;
|
|
27371
|
+
}
|
|
27372
|
+
const kind = classifyDiffFileKind(f2);
|
|
27373
|
+
if (!kind.heavy && !kind.binary && !kind.media)
|
|
27374
|
+
return null;
|
|
27375
|
+
const tag = document.createElement("span");
|
|
27376
|
+
const isBinaryLike = kind.binary || kind.media;
|
|
27377
|
+
tag.className = `kind-tag ${isBinaryLike ? "binary" : "heavy"}`;
|
|
27378
|
+
tag.textContent = isBinaryLike ? "B" : "!";
|
|
27379
|
+
tag.title = isBinaryLike ? "binary/media file" : "large diff";
|
|
27380
|
+
return tag;
|
|
27381
|
+
}
|
|
27382
|
+
function sidebarEntryIcon(f2) {
|
|
27383
|
+
return f2.type === "commit" ? iconSvg("octicon-git-branch", GIT_BRANCH_16_PATH) : fileEntryIcon();
|
|
27384
|
+
}
|
|
26107
27385
|
function createTreeFileRow(f2, depth, onFileClick) {
|
|
26108
27386
|
const li = document.createElement("li");
|
|
26109
27387
|
li.className = "tree-file";
|
|
26110
27388
|
li.tabIndex = -1;
|
|
26111
27389
|
li.dataset.path = f2.path;
|
|
26112
|
-
li.dataset.type = "blob";
|
|
27390
|
+
li.dataset.type = f2.type || "blob";
|
|
27391
|
+
if (f2.type === "commit") {
|
|
27392
|
+
li.title = commitEntryBadge(f2.submodule).title;
|
|
27393
|
+
}
|
|
26113
27394
|
li.classList.toggle("viewed", !onFileClick && STATE.viewedFiles.has(f2.path));
|
|
26114
27395
|
li.classList.toggle("hidden-by-tests", STATE.hideTests && !isRepositorySidebarMode() && isTestPath(f2.path || ""));
|
|
26115
27396
|
li.style.setProperty("--lvl-pad", `${12 + depth * 14}px`);
|
|
@@ -26121,7 +27402,7 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
26121
27402
|
} else {
|
|
26122
27403
|
const icon = document.createElement("span");
|
|
26123
27404
|
icon.className = "d2h-icon-wrapper";
|
|
26124
|
-
icon.innerHTML =
|
|
27405
|
+
icon.innerHTML = sidebarEntryIcon(f2);
|
|
26125
27406
|
li.appendChild(icon);
|
|
26126
27407
|
}
|
|
26127
27408
|
const name = document.createElement("span");
|
|
@@ -26129,6 +27410,9 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
26129
27410
|
name.textContent = f2.path.split("/").pop();
|
|
26130
27411
|
name.title = f2.path;
|
|
26131
27412
|
li.appendChild(name);
|
|
27413
|
+
const kindTag = fileKindTag(f2);
|
|
27414
|
+
if (kindTag)
|
|
27415
|
+
li.appendChild(kindTag);
|
|
26132
27416
|
li.addEventListener("click", () => {
|
|
26133
27417
|
if (onFileClick)
|
|
26134
27418
|
onFileClick(f2);
|
|
@@ -26336,13 +27620,17 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
26336
27620
|
li.tabIndex = -1;
|
|
26337
27621
|
li.dataset.index = String(i2);
|
|
26338
27622
|
li.dataset.path = f2.path;
|
|
27623
|
+
li.dataset.type = f2.type || "blob";
|
|
27624
|
+
if (f2.type === "commit") {
|
|
27625
|
+
li.title = commitEntryBadge(f2.submodule).title;
|
|
27626
|
+
}
|
|
26339
27627
|
li.classList.toggle("viewed", !onFileClick && STATE.viewedFiles.has(f2.path));
|
|
26340
27628
|
if (f2.status) {
|
|
26341
27629
|
li.appendChild(fileBadge(f2.status));
|
|
26342
27630
|
} else {
|
|
26343
27631
|
const icon = document.createElement("span");
|
|
26344
27632
|
icon.className = "d2h-icon-wrapper";
|
|
26345
|
-
icon.innerHTML =
|
|
27633
|
+
icon.innerHTML = sidebarEntryIcon(f2);
|
|
26346
27634
|
li.appendChild(icon);
|
|
26347
27635
|
}
|
|
26348
27636
|
const name = document.createElement("span");
|
|
@@ -26350,6 +27638,9 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
26350
27638
|
name.textContent = f2.path;
|
|
26351
27639
|
name.title = f2.path;
|
|
26352
27640
|
li.appendChild(name);
|
|
27641
|
+
const kindTag = fileKindTag(f2);
|
|
27642
|
+
if (kindTag)
|
|
27643
|
+
li.appendChild(kindTag);
|
|
26353
27644
|
li.addEventListener("click", () => {
|
|
26354
27645
|
if (onFileClick)
|
|
26355
27646
|
onFileClick(f2);
|
|
@@ -26517,6 +27808,7 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
26517
27808
|
}
|
|
26518
27809
|
function applyFilter() {
|
|
26519
27810
|
const input = $("#sb-filter");
|
|
27811
|
+
syncSidebarFilterClearButton();
|
|
26520
27812
|
if ($("#filelist").classList.contains("tree-virtual")) {
|
|
26521
27813
|
rerenderVirtualSidebar();
|
|
26522
27814
|
return;
|
|
@@ -26582,6 +27874,23 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
26582
27874
|
SIDEBAR_FILTER_RAF = 0;
|
|
26583
27875
|
applyFilter();
|
|
26584
27876
|
}
|
|
27877
|
+
function syncSidebarFilterClearButton() {
|
|
27878
|
+
const input = document.querySelector("#sb-filter");
|
|
27879
|
+
const button = document.querySelector("#sb-filter-clear");
|
|
27880
|
+
if (!input || !button)
|
|
27881
|
+
return;
|
|
27882
|
+
button.hidden = input.value.length === 0;
|
|
27883
|
+
}
|
|
27884
|
+
function clearSidebarFilter() {
|
|
27885
|
+
const input = document.querySelector("#sb-filter");
|
|
27886
|
+
if (!input?.value)
|
|
27887
|
+
return;
|
|
27888
|
+
input.value = "";
|
|
27889
|
+
syncSidebarFilterClearButton();
|
|
27890
|
+
flushSidebarFilter();
|
|
27891
|
+
applyFilter();
|
|
27892
|
+
input.focus();
|
|
27893
|
+
}
|
|
26585
27894
|
function applySidebarWidth(w, options = {}) {
|
|
26586
27895
|
const cw = Math.max(180, Math.min(900, w));
|
|
26587
27896
|
document.documentElement.style.setProperty("--sidebar-w", `${cw}px`);
|
|
@@ -26917,6 +28226,8 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
26917
28226
|
applyFilter,
|
|
26918
28227
|
scheduleApplyFilter,
|
|
26919
28228
|
flushSidebarFilter,
|
|
28229
|
+
syncSidebarFilterClearButton,
|
|
28230
|
+
clearSidebarFilter,
|
|
26920
28231
|
markActive,
|
|
26921
28232
|
rerenderVirtualSidebar,
|
|
26922
28233
|
ensureVirtualSidebarDirLoaded,
|
|
@@ -27002,7 +28313,19 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
27002
28313
|
syncHeaderMenu,
|
|
27003
28314
|
getSidebarRowByPath,
|
|
27004
28315
|
getSidebarVirtualActivePath,
|
|
27005
|
-
pushUndo
|
|
28316
|
+
pushUndo,
|
|
28317
|
+
newFolderButtonTitle,
|
|
28318
|
+
openDirectoryInOsTitle,
|
|
28319
|
+
moveFolderToTrashTitle,
|
|
28320
|
+
uploadButtonLabel,
|
|
28321
|
+
dropFilesIntoCopy,
|
|
28322
|
+
uploadFailedMessage,
|
|
28323
|
+
emptyDirectoryLabel,
|
|
28324
|
+
uploadConfirmText,
|
|
28325
|
+
sortColumnLabels,
|
|
28326
|
+
repositoryFallback,
|
|
28327
|
+
repositoryRootFallback,
|
|
28328
|
+
commitEntryMeta
|
|
27006
28329
|
} = deps;
|
|
27007
28330
|
let REPO_SORT = {
|
|
27008
28331
|
key: "name",
|
|
@@ -27045,6 +28368,15 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
27045
28368
|
function fileEntryIcon() {
|
|
27046
28369
|
return iconSvg("octicon-file", FILE_16_PATH);
|
|
27047
28370
|
}
|
|
28371
|
+
function commitEntryIcon() {
|
|
28372
|
+
return iconSvg("octicon-git-branch", GIT_BRANCH_16_PATH);
|
|
28373
|
+
}
|
|
28374
|
+
function isWorktreeRef(ref) {
|
|
28375
|
+
return canTrashWorktreeRef(ref);
|
|
28376
|
+
}
|
|
28377
|
+
function canBrowseRepoEntry(entry, ref) {
|
|
28378
|
+
return entry.type === "tree" || entry.type === "commit" && isWorktreeRef(ref) && !entry.submodule;
|
|
28379
|
+
}
|
|
27048
28380
|
function closeRepoContextMenu() {
|
|
27049
28381
|
document.querySelector(".gdp-context-menu")?.remove();
|
|
27050
28382
|
}
|
|
@@ -27223,8 +28555,9 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
27223
28555
|
const button = document.createElement("button");
|
|
27224
28556
|
button.type = "button";
|
|
27225
28557
|
button.className = "gdp-file-header-icon gdp-trash-path";
|
|
27226
|
-
|
|
27227
|
-
button.
|
|
28558
|
+
const trashTitle = moveFolderToTrashTitle();
|
|
28559
|
+
button.title = trashTitle;
|
|
28560
|
+
button.setAttribute("aria-label", trashTitle);
|
|
27228
28561
|
button.innerHTML = iconSvg("octicon-trash", TRASH_16_PATH);
|
|
27229
28562
|
button.addEventListener("click", async (event) => {
|
|
27230
28563
|
event.stopPropagation();
|
|
@@ -27236,8 +28569,9 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
27236
28569
|
const button = document.createElement("button");
|
|
27237
28570
|
button.type = "button";
|
|
27238
28571
|
button.className = "gdp-file-header-icon gdp-create-dir";
|
|
27239
|
-
|
|
27240
|
-
button.
|
|
28572
|
+
const newFolderTitle = newFolderButtonTitle();
|
|
28573
|
+
button.title = newFolderTitle;
|
|
28574
|
+
button.setAttribute("aria-label", newFolderTitle);
|
|
27241
28575
|
button.innerHTML = iconSvg("octicon-plus", PLUS_16_PATH);
|
|
27242
28576
|
button.addEventListener("click", async (event) => {
|
|
27243
28577
|
event.stopPropagation();
|
|
@@ -27252,7 +28586,7 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
27252
28586
|
dropPanel.className = "gdp-upload-panel";
|
|
27253
28587
|
const copy = document.createElement("div");
|
|
27254
28588
|
copy.className = "gdp-upload-copy";
|
|
27255
|
-
copy.textContent =
|
|
28589
|
+
copy.textContent = dropFilesIntoCopy(path || getProjectName() || repositoryFallback());
|
|
27256
28590
|
const input = document.createElement("input");
|
|
27257
28591
|
input.type = "file";
|
|
27258
28592
|
input.multiple = true;
|
|
@@ -27260,11 +28594,11 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
27260
28594
|
const button = document.createElement("button");
|
|
27261
28595
|
button.type = "button";
|
|
27262
28596
|
button.className = "gdp-btn gdp-btn-sm";
|
|
27263
|
-
button.textContent =
|
|
28597
|
+
button.textContent = uploadButtonLabel();
|
|
27264
28598
|
button.addEventListener("click", () => input.click());
|
|
27265
28599
|
const error2 = document.createElement("div");
|
|
27266
28600
|
error2.className = "gdp-upload-error";
|
|
27267
|
-
const fail = (message =
|
|
28601
|
+
const fail = (message = uploadFailedMessage()) => {
|
|
27268
28602
|
error2.textContent = message;
|
|
27269
28603
|
dropPanel.classList.add("failed");
|
|
27270
28604
|
setTimeout(() => dropPanel.classList.remove("failed"), 1600);
|
|
@@ -27275,7 +28609,7 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
27275
28609
|
await uploadFiles(path, input.files);
|
|
27276
28610
|
error2.textContent = "";
|
|
27277
28611
|
} catch (uploadError) {
|
|
27278
|
-
fail(uploadError instanceof Error ? uploadError.message :
|
|
28612
|
+
fail(uploadError instanceof Error ? uploadError.message : uploadFailedMessage());
|
|
27279
28613
|
} finally {
|
|
27280
28614
|
input.value = "";
|
|
27281
28615
|
}
|
|
@@ -27294,7 +28628,7 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
27294
28628
|
await uploadFiles(path, files);
|
|
27295
28629
|
error2.textContent = "";
|
|
27296
28630
|
} catch (uploadError) {
|
|
27297
|
-
fail(uploadError instanceof Error ? uploadError.message :
|
|
28631
|
+
fail(uploadError instanceof Error ? uploadError.message : uploadFailedMessage());
|
|
27298
28632
|
}
|
|
27299
28633
|
});
|
|
27300
28634
|
dropPanel.append(copy, button, input, error2);
|
|
@@ -27314,7 +28648,7 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
27314
28648
|
const root = document.createElement("button");
|
|
27315
28649
|
root.type = "button";
|
|
27316
28650
|
root.className = path ? "gdp-file-breadcrumb-part" : "gdp-file-breadcrumb-current";
|
|
27317
|
-
root.textContent = getProjectName() ||
|
|
28651
|
+
root.textContent = getProjectName() || repositoryFallback();
|
|
27318
28652
|
root.addEventListener("click", () => {
|
|
27319
28653
|
setRoute(repoRoute(target, ""));
|
|
27320
28654
|
loadRepo();
|
|
@@ -27361,7 +28695,7 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
27361
28695
|
pathHeader.appendChild(createRepoBreadcrumb(meta.ref, meta.path || ""));
|
|
27362
28696
|
if (meta.path)
|
|
27363
28697
|
pathHeader.appendChild(createCopyPathButton(meta.path));
|
|
27364
|
-
pathHeader.appendChild(createOpenPathButton(meta.path || "", "directory",
|
|
28698
|
+
pathHeader.appendChild(createOpenPathButton(meta.path || "", "directory", openDirectoryInOsTitle()));
|
|
27365
28699
|
toolbar.appendChild(pathHeader);
|
|
27366
28700
|
if (canTrashWorktreeRef(meta.ref)) {
|
|
27367
28701
|
toolbar.appendChild(createNewFolderButton(meta.path || "", () => loadRepo()));
|
|
@@ -27414,24 +28748,30 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
27414
28748
|
});
|
|
27415
28749
|
list2.appendChild(row);
|
|
27416
28750
|
}
|
|
27417
|
-
sortedRepoEntries(meta.entries).forEach((entry) => {
|
|
28751
|
+
sortedRepoEntries(meta.entries, meta.ref).forEach((entry) => {
|
|
28752
|
+
const browsable = canBrowseRepoEntry(entry, meta.ref);
|
|
28753
|
+
const nonBrowsableCommit = entry.type === "commit" && !browsable;
|
|
27418
28754
|
const row = document.createElement("button");
|
|
27419
28755
|
row.type = "button";
|
|
27420
|
-
row.className = `gdp-repo-row ${entry.type}`;
|
|
28756
|
+
row.className = nonBrowsableCommit ? `gdp-repo-row ${entry.type} gdp-repo-row-gitlink` : `gdp-repo-row ${entry.type}`;
|
|
27421
28757
|
const icon = document.createElement("span");
|
|
27422
|
-
icon.className =
|
|
27423
|
-
if (
|
|
28758
|
+
icon.className = browsable ? "dir-icon" : nonBrowsableCommit ? "d2h-icon-wrapper gdp-repo-row-gitlink-icon" : "d2h-icon-wrapper";
|
|
28759
|
+
if (browsable)
|
|
27424
28760
|
setFolderIcon(icon, true);
|
|
27425
28761
|
else
|
|
27426
|
-
icon.innerHTML = fileEntryIcon();
|
|
28762
|
+
icon.innerHTML = entry.type === "commit" ? commitEntryIcon() : fileEntryIcon();
|
|
27427
28763
|
const name = document.createElement("span");
|
|
27428
28764
|
name.className = "name";
|
|
27429
28765
|
name.textContent = entry.name;
|
|
27430
|
-
|
|
28766
|
+
if (nonBrowsableCommit) {
|
|
28767
|
+
row.title = commitEntryMeta(entry.submodule).title;
|
|
28768
|
+
row.setAttribute("aria-disabled", "true");
|
|
28769
|
+
}
|
|
28770
|
+
const metaBlock = createRepoEntryMeta(entry, browsable);
|
|
27431
28771
|
const size = createRepoEntrySize(entry);
|
|
27432
28772
|
row.append(icon, name, metaBlock, size);
|
|
27433
28773
|
row.addEventListener("click", () => {
|
|
27434
|
-
if (
|
|
28774
|
+
if (browsable) {
|
|
27435
28775
|
setRoute(repoRoute(meta.ref, entry.path));
|
|
27436
28776
|
loadRepo();
|
|
27437
28777
|
} else if (entry.type === "blob") {
|
|
@@ -27451,7 +28791,7 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
27451
28791
|
if (!meta.entries.length) {
|
|
27452
28792
|
const empty = document.createElement("div");
|
|
27453
28793
|
empty.className = "gdp-repo-empty";
|
|
27454
|
-
empty.textContent =
|
|
28794
|
+
empty.textContent = emptyDirectoryLabel();
|
|
27455
28795
|
list2.appendChild(empty);
|
|
27456
28796
|
}
|
|
27457
28797
|
};
|
|
@@ -27538,7 +28878,8 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
27538
28878
|
order: index + 1,
|
|
27539
28879
|
path: entry.path,
|
|
27540
28880
|
display_path: entry.path,
|
|
27541
|
-
type: entry.type,
|
|
28881
|
+
type: canBrowseRepoEntry(entry, normalizedRef) ? "tree" : entry.type,
|
|
28882
|
+
submodule: entry.submodule,
|
|
27542
28883
|
children_omitted: entry.children_omitted,
|
|
27543
28884
|
children_omitted_reason: entry.children_omitted_reason
|
|
27544
28885
|
}));
|
|
@@ -27601,12 +28942,19 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
27601
28942
|
}
|
|
27602
28943
|
});
|
|
27603
28944
|
}
|
|
27604
|
-
function createRepoEntryMeta(entry) {
|
|
28945
|
+
function createRepoEntryMeta(entry, browsable) {
|
|
27605
28946
|
const meta = document.createElement("span");
|
|
27606
28947
|
meta.className = "meta";
|
|
28948
|
+
if (entry.type === "commit" && !browsable) {
|
|
28949
|
+
meta.classList.add("gdp-repo-row-gitlink-badge");
|
|
28950
|
+
const badge = commitEntryMeta(entry.submodule);
|
|
28951
|
+
meta.textContent = badge.label;
|
|
28952
|
+
meta.title = badge.title;
|
|
28953
|
+
return meta;
|
|
28954
|
+
}
|
|
27607
28955
|
const updated = formatFileDate(entry.updated_at || entry.commit_updated_at);
|
|
27608
28956
|
const created = formatFileDate(entry.created_at);
|
|
27609
|
-
if (
|
|
28957
|
+
if (browsable && updated) {
|
|
27610
28958
|
meta.textContent = updated;
|
|
27611
28959
|
if (created)
|
|
27612
28960
|
meta.title = `Created ${created}`;
|
|
@@ -27634,13 +28982,15 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
27634
28982
|
const time = new Date(raw).getTime();
|
|
27635
28983
|
return Number.isNaN(time) ? -1 : time;
|
|
27636
28984
|
}
|
|
27637
|
-
function sortedRepoEntries(entries) {
|
|
28985
|
+
function sortedRepoEntries(entries, ref = "worktree") {
|
|
27638
28986
|
const direction = REPO_SORT.direction === "asc" ? 1 : -1;
|
|
27639
28987
|
return [...entries].sort((a2, b2) => {
|
|
27640
|
-
|
|
27641
|
-
|
|
28988
|
+
const aBrowsable = canBrowseRepoEntry(a2, ref);
|
|
28989
|
+
const bBrowsable = canBrowseRepoEntry(b2, ref);
|
|
28990
|
+
if (REPO_SORT.key === "name" && aBrowsable !== bBrowsable) {
|
|
28991
|
+
if (aBrowsable)
|
|
27642
28992
|
return -1;
|
|
27643
|
-
if (
|
|
28993
|
+
if (bBrowsable)
|
|
27644
28994
|
return 1;
|
|
27645
28995
|
}
|
|
27646
28996
|
let result = 0;
|
|
@@ -27672,10 +29022,11 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
27672
29022
|
const spacer = document.createElement("span");
|
|
27673
29023
|
spacer.className = "gdp-repo-sort-spacer";
|
|
27674
29024
|
header.appendChild(spacer);
|
|
29025
|
+
const sortLabels = sortColumnLabels();
|
|
27675
29026
|
const columns = [
|
|
27676
|
-
{ key: "name", label:
|
|
27677
|
-
{ key: "updated", label:
|
|
27678
|
-
{ key: "size", label:
|
|
29027
|
+
{ key: "name", label: sortLabels.name },
|
|
29028
|
+
{ key: "updated", label: sortLabels.updated },
|
|
29029
|
+
{ key: "size", label: sortLabels.size }
|
|
27679
29030
|
];
|
|
27680
29031
|
columns.forEach((column) => {
|
|
27681
29032
|
const button = document.createElement("button");
|
|
@@ -27798,11 +29149,12 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
27798
29149
|
const list2 = Array.from(files);
|
|
27799
29150
|
if (!list2.length)
|
|
27800
29151
|
return;
|
|
27801
|
-
const label = path || getProjectName() ||
|
|
29152
|
+
const label = path || getProjectName() || repositoryRootFallback();
|
|
29153
|
+
const confirmText = uploadConfirmText(list2.length, label);
|
|
27802
29154
|
const ok = await showConfirmDialog({
|
|
27803
|
-
title:
|
|
27804
|
-
body:
|
|
27805
|
-
confirmLabel:
|
|
29155
|
+
title: confirmText.title,
|
|
29156
|
+
body: confirmText.body,
|
|
29157
|
+
confirmLabel: confirmText.confirmLabel
|
|
27806
29158
|
});
|
|
27807
29159
|
if (!ok)
|
|
27808
29160
|
return;
|
|
@@ -30176,13 +31528,20 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
30176
31528
|
const loadBar = document.querySelector("#load-bar");
|
|
30177
31529
|
if (loadBar)
|
|
30178
31530
|
loadBar.classList.toggle("active", state.inFlight > 0);
|
|
31531
|
+
const text2 = uiText().global;
|
|
31532
|
+
const statusEl = document.querySelector("#status");
|
|
31533
|
+
if (statusEl) {
|
|
31534
|
+
statusEl.title = state.inFlight > 0 ? text2.statusInFlightTitle(state.inFlight, state.cancellable) : statusEl.querySelector(".status-label")?.textContent ?? "";
|
|
31535
|
+
}
|
|
30179
31536
|
const cancelButton = document.querySelector("#cancel-requests");
|
|
30180
31537
|
if (!cancelButton)
|
|
30181
31538
|
return;
|
|
30182
31539
|
const cancellable = state.cancellable > 0;
|
|
30183
31540
|
cancelButton.disabled = !cancellable;
|
|
30184
31541
|
cancelButton.classList.toggle("active", cancellable);
|
|
30185
|
-
|
|
31542
|
+
const cancelTitle = cancellable ? text2.cancelRequestsActiveTitle(state.cancellable) : text2.cancelRequestsInactiveTitle;
|
|
31543
|
+
cancelButton.title = cancelTitle;
|
|
31544
|
+
cancelButton.setAttribute("aria-label", cancelTitle);
|
|
30186
31545
|
}
|
|
30187
31546
|
function cancelInFlightRequests() {
|
|
30188
31547
|
NETWORK_ACTIVITY.cancelAll();
|
|
@@ -30695,13 +32054,31 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
30695
32054
|
setRepoSidebarRef: (ref) => {
|
|
30696
32055
|
REPO_SIDEBAR_REF = ref;
|
|
30697
32056
|
},
|
|
30698
|
-
isTestPath: (path) => TEST_RE.test(path)
|
|
32057
|
+
isTestPath: (path) => TEST_RE.test(path),
|
|
32058
|
+
sidebarToggleTitle: (hidden) => hidden ? uiText().sidebar.show : uiText().sidebar.hide,
|
|
32059
|
+
openDirectoryInOsTitle: () => uiText().sidebar.openDirectoryInOs,
|
|
32060
|
+
omittedDirectoryBadge: (reason) => {
|
|
32061
|
+
const text2 = uiText().sidebar;
|
|
32062
|
+
return reason === "heavy" ? { label: text2.omittedHeavyLabel, title: text2.omittedHeavyTitle } : { label: text2.omittedPrivateLabel, title: text2.omittedPrivateTitle };
|
|
32063
|
+
},
|
|
32064
|
+
commitEntryBadge: (submodule) => {
|
|
32065
|
+
const text2 = uiText().sidebar;
|
|
32066
|
+
return submodule ? {
|
|
32067
|
+
label: text2.commitEntrySubmoduleLabel,
|
|
32068
|
+
title: text2.commitEntrySubmoduleTitle
|
|
32069
|
+
} : {
|
|
32070
|
+
label: text2.commitEntryGitlinkLabel,
|
|
32071
|
+
title: text2.commitEntryGitlinkTitle
|
|
32072
|
+
};
|
|
32073
|
+
}
|
|
30699
32074
|
});
|
|
30700
32075
|
const {
|
|
30701
32076
|
renderSidebar,
|
|
30702
32077
|
applyFilter,
|
|
30703
32078
|
scheduleApplyFilter,
|
|
30704
32079
|
flushSidebarFilter,
|
|
32080
|
+
syncSidebarFilterClearButton,
|
|
32081
|
+
clearSidebarFilter,
|
|
30705
32082
|
markActive,
|
|
30706
32083
|
rerenderVirtualSidebar,
|
|
30707
32084
|
ensureVirtualSidebarDirLoaded,
|
|
@@ -30838,6 +32215,35 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
30838
32215
|
getSidebarVirtualActivePath,
|
|
30839
32216
|
pushUndo: (undo) => {
|
|
30840
32217
|
UNDO_STACK.unshift(undo);
|
|
32218
|
+
},
|
|
32219
|
+
newFolderButtonTitle: () => uiText().repo.newFolder,
|
|
32220
|
+
openDirectoryInOsTitle: () => uiText().sidebar.openDirectoryInOs,
|
|
32221
|
+
moveFolderToTrashTitle: () => uiText().repo.moveFolderToTrash,
|
|
32222
|
+
uploadButtonLabel: () => uiText().repo.uploadButton,
|
|
32223
|
+
dropFilesIntoCopy: (target) => uiText().repo.dropFilesInto(target),
|
|
32224
|
+
uploadFailedMessage: () => uiText().repo.uploadFailed,
|
|
32225
|
+
emptyDirectoryLabel: () => uiText().repo.emptyDirectory,
|
|
32226
|
+
uploadConfirmText: (count, target) => {
|
|
32227
|
+
const text2 = uiText().repo;
|
|
32228
|
+
return {
|
|
32229
|
+
title: text2.uploadConfirmTitle,
|
|
32230
|
+
body: text2.uploadConfirmBody(count, target),
|
|
32231
|
+
confirmLabel: text2.uploadConfirmLabel
|
|
32232
|
+
};
|
|
32233
|
+
},
|
|
32234
|
+
sortColumnLabels: () => {
|
|
32235
|
+
const text2 = uiText().repo;
|
|
32236
|
+
return {
|
|
32237
|
+
name: text2.sortName,
|
|
32238
|
+
updated: text2.sortUpdated,
|
|
32239
|
+
size: text2.sortSize
|
|
32240
|
+
};
|
|
32241
|
+
},
|
|
32242
|
+
repositoryFallback: () => uiText().repo.repositoryFallback,
|
|
32243
|
+
repositoryRootFallback: () => uiText().repo.repositoryRootFallback,
|
|
32244
|
+
commitEntryMeta: (submodule) => {
|
|
32245
|
+
const text2 = uiText().repo;
|
|
32246
|
+
return submodule ? { label: text2.submoduleLabel, title: text2.submoduleTitle } : { label: text2.gitlinkLabel, title: text2.gitlinkTitle };
|
|
30841
32247
|
}
|
|
30842
32248
|
});
|
|
30843
32249
|
const {
|
|
@@ -30880,10 +32286,20 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
30880
32286
|
theme: "toggle theme",
|
|
30881
32287
|
product: "code viewer",
|
|
30882
32288
|
copyAiContext: "Copy AI context (Shift+Click to include code)",
|
|
32289
|
+
copyAiContextLabel: "AI context",
|
|
30883
32290
|
copyAiContextCopied: "Copied AI context",
|
|
30884
32291
|
copyAiContextCopiedWithCode: (lines) => `Copied AI context + code (${lines} line${lines === 1 ? "" : "s"})`,
|
|
30885
32292
|
copyAiContextFailed: "Copy failed",
|
|
30886
|
-
copyAiContextEmpty: "Nothing to copy here"
|
|
32293
|
+
copyAiContextEmpty: "Nothing to copy here",
|
|
32294
|
+
statusLive: "Live",
|
|
32295
|
+
statusLoading: "Loading",
|
|
32296
|
+
statusError: "Error",
|
|
32297
|
+
statusIdle: "Idle",
|
|
32298
|
+
statusInFlightTitle: (count, cancellable) => `${count} request${count === 1 ? "" : "s"} in flight${cancellable > 0 ? " (cancellable)" : ""}`,
|
|
32299
|
+
cancelRequestsActiveTitle: (count) => `cancel ${count} in-flight request${count === 1 ? "" : "s"}`,
|
|
32300
|
+
cancelRequestsInactiveTitle: "no in-flight requests",
|
|
32301
|
+
brandHome: "Repository home",
|
|
32302
|
+
menuViews: "Views"
|
|
30887
32303
|
},
|
|
30888
32304
|
topbar: {
|
|
30889
32305
|
resetRange: "reset to HEAD .. worktree",
|
|
@@ -30892,6 +32308,7 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
30892
32308
|
unified: "unified",
|
|
30893
32309
|
split: "split",
|
|
30894
32310
|
ignoreWs: "ignore whitespace changes (-w)",
|
|
32311
|
+
ignoreWsLabel: "ws",
|
|
30895
32312
|
syntaxLoading: "loading...",
|
|
30896
32313
|
syntaxOn: "syntax on",
|
|
30897
32314
|
syntaxOff: "syntax off",
|
|
@@ -30900,10 +32317,38 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
30900
32317
|
syntaxErrorTitle: "failed to load syntax highlighter",
|
|
30901
32318
|
syntaxOffTitle: "syntax highlighting off",
|
|
30902
32319
|
hideTests: "hide test files (test|spec)",
|
|
32320
|
+
hideTestsLabel: "no test",
|
|
30903
32321
|
autoUpdate: "auto",
|
|
30904
32322
|
autoUpdateOnTitle: "auto update on file change",
|
|
30905
32323
|
autoUpdateOffTitle: "auto update off — manual reload"
|
|
30906
32324
|
},
|
|
32325
|
+
diff: {
|
|
32326
|
+
files: (count) => `${count} file${count === 1 ? "" : "s"}`,
|
|
32327
|
+
updated: (time) => `updated ${time}`,
|
|
32328
|
+
updatedTitle: "last updated",
|
|
32329
|
+
kindAdded: "added",
|
|
32330
|
+
kindDeleted: "deleted",
|
|
32331
|
+
kindRenamed: "renamed",
|
|
32332
|
+
kindHeavy: "heavy",
|
|
32333
|
+
kindBinary: "binary",
|
|
32334
|
+
kindMedia: "media",
|
|
32335
|
+
viewedProgress: (viewed, total) => `${viewed}/${total} viewed`,
|
|
32336
|
+
viewedProgressTitle: "review progress",
|
|
32337
|
+
nextUnviewed: "next unviewed",
|
|
32338
|
+
nextUnviewedTitle: "Jump to the next unviewed file (n)",
|
|
32339
|
+
allViewed: "all viewed",
|
|
32340
|
+
allViewedTitle: "All visible files are viewed",
|
|
32341
|
+
noChangesTitle: "No changes",
|
|
32342
|
+
noChangesBody: "The working tree is clean against this ref.",
|
|
32343
|
+
noChangesReload: "Reload diff",
|
|
32344
|
+
noChangesReloadTitle: "Reload this diff range",
|
|
32345
|
+
noChangesHistory: "Open history",
|
|
32346
|
+
noChangesHistoryTitle: "Open commit history for this range",
|
|
32347
|
+
emptyDiffTitle: "Empty diff",
|
|
32348
|
+
emptyDiffBody: "This commit has no changes against its first parent.",
|
|
32349
|
+
noCommitSelectedTitle: "No commit selected",
|
|
32350
|
+
noCommitSelectedBody: "Select a commit from the list to see its changes."
|
|
32351
|
+
},
|
|
30907
32352
|
changeBanner: {
|
|
30908
32353
|
text: "Files changed",
|
|
30909
32354
|
reload: "Reload",
|
|
@@ -30923,14 +32368,56 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
30923
32368
|
view: "view",
|
|
30924
32369
|
tree: "tree",
|
|
30925
32370
|
flat: "flat",
|
|
32371
|
+
treeTitle: "tree view",
|
|
32372
|
+
flatTitle: "flat list",
|
|
30926
32373
|
filter: "Filter files… / ⌘K",
|
|
30927
32374
|
filterTitle: "Filter files. Use /pattern/ for regex. Press / to focus this field, Cmd/Ctrl+K for the full-file palette, Ctrl+G for grep, ? for help.",
|
|
30928
|
-
|
|
32375
|
+
filterClear: "Clear",
|
|
32376
|
+
filterClearTitle: "Clear file filter",
|
|
32377
|
+
hide: "hide sidebar",
|
|
32378
|
+
show: "show sidebar",
|
|
32379
|
+
repoTarget: "repository target",
|
|
32380
|
+
openDirectoryInOs: "open this folder in OS",
|
|
32381
|
+
omittedHeavyLabel: "skipped",
|
|
32382
|
+
omittedHeavyTitle: "Tree expansion is skipped, but the directory detail can be opened",
|
|
32383
|
+
omittedPrivateLabel: "private",
|
|
32384
|
+
omittedPrivateTitle: "This directory cannot be opened from the browser",
|
|
32385
|
+
commitEntryGitlinkLabel: "GIT",
|
|
32386
|
+
commitEntryGitlinkTitle: "Git commit entry",
|
|
32387
|
+
commitEntrySubmoduleLabel: "SUB",
|
|
32388
|
+
commitEntrySubmoduleTitle: "Git submodule pinned to a commit"
|
|
32389
|
+
},
|
|
32390
|
+
repo: {
|
|
32391
|
+
newFolder: "new folder",
|
|
32392
|
+
moveFolderToTrash: "move folder to Trash",
|
|
32393
|
+
uploadButton: "Upload files",
|
|
32394
|
+
dropFilesInto: (target) => `Drop files into ${target}`,
|
|
32395
|
+
uploadFailed: "Upload failed",
|
|
32396
|
+
emptyDirectory: "No files in this directory.",
|
|
32397
|
+
uploadConfirmTitle: "Upload files?",
|
|
32398
|
+
uploadConfirmBody: (count, target) => `Upload ${count} file${count === 1 ? "" : "s"} into ${target}?`,
|
|
32399
|
+
uploadConfirmLabel: "Upload",
|
|
32400
|
+
sortName: "Name",
|
|
32401
|
+
sortUpdated: "Updated",
|
|
32402
|
+
sortSize: "Size",
|
|
32403
|
+
repositoryFallback: "repository",
|
|
32404
|
+
repositoryRootFallback: "repository root",
|
|
32405
|
+
gitlinkLabel: "gitlink",
|
|
32406
|
+
gitlinkTitle: "Git commit entry is not directly browsable at this ref",
|
|
32407
|
+
submoduleLabel: "submodule",
|
|
32408
|
+
submoduleTitle: "Git submodule pinned to a commit"
|
|
30929
32409
|
},
|
|
30930
32410
|
history: {
|
|
30931
32411
|
title: "Commits",
|
|
30932
32412
|
filter: "Filter commits...",
|
|
30933
|
-
filterTitle: "Filter commits by message, SHA, author:name, or path:file."
|
|
32413
|
+
filterTitle: "Filter commits by message, SHA, author:name, or path:file.",
|
|
32414
|
+
refreshTitle: "Refresh commit history"
|
|
32415
|
+
},
|
|
32416
|
+
quickHelp: {
|
|
32417
|
+
buttonTitle: "quick help (shortcuts)",
|
|
32418
|
+
panelTitle: "Quick Help",
|
|
32419
|
+
close: "close quick help",
|
|
32420
|
+
viewAll: "View all keybindings →"
|
|
30934
32421
|
},
|
|
30935
32422
|
settings: {
|
|
30936
32423
|
title: "Viewer Settings",
|
|
@@ -30991,30 +32478,69 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
30991
32478
|
theme: "テーマ切り替え",
|
|
30992
32479
|
product: "code viewer",
|
|
30993
32480
|
copyAiContext: "AI 用コンテキストをコピー(Shift+Click でコードも添付)",
|
|
32481
|
+
copyAiContextLabel: "AI文脈",
|
|
30994
32482
|
copyAiContextCopied: "コピーしました",
|
|
30995
32483
|
copyAiContextCopiedWithCode: (lines) => `コピーしました(コード付き・${lines}行)`,
|
|
30996
32484
|
copyAiContextFailed: "コピーに失敗しました",
|
|
30997
|
-
copyAiContextEmpty: "コピーする内容がありません"
|
|
32485
|
+
copyAiContextEmpty: "コピーする内容がありません",
|
|
32486
|
+
statusLive: "稼働中",
|
|
32487
|
+
statusLoading: "更新中",
|
|
32488
|
+
statusError: "エラー",
|
|
32489
|
+
statusIdle: "待機中",
|
|
32490
|
+
statusInFlightTitle: (count, cancellable) => `${count}件のリクエストを実行中${cancellable > 0 ? "(キャンセル可能)" : ""}`,
|
|
32491
|
+
cancelRequestsActiveTitle: (count) => `実行中のリクエストを${count}件キャンセル`,
|
|
32492
|
+
cancelRequestsInactiveTitle: "実行中のリクエストはありません",
|
|
32493
|
+
brandHome: "リポジトリホーム",
|
|
32494
|
+
menuViews: "ビュー切り替え"
|
|
30998
32495
|
},
|
|
30999
32496
|
topbar: {
|
|
31000
32497
|
resetRange: "HEAD .. worktree に戻す",
|
|
31001
32498
|
reload: "diff を再読み込み (R)",
|
|
31002
32499
|
layout: "レイアウト",
|
|
31003
|
-
unified: "
|
|
31004
|
-
split: "
|
|
32500
|
+
unified: "統合",
|
|
32501
|
+
split: "分割",
|
|
31005
32502
|
ignoreWs: "空白差分を無視 (-w)",
|
|
32503
|
+
ignoreWsLabel: "空白",
|
|
31006
32504
|
syntaxLoading: "読み込み中...",
|
|
31007
|
-
syntaxOn: "
|
|
31008
|
-
syntaxOff: "
|
|
32505
|
+
syntaxOn: "構文あり",
|
|
32506
|
+
syntaxOff: "構文なし",
|
|
31009
32507
|
syntaxOnTitle: "シンタックスハイライト有効",
|
|
31010
32508
|
syntaxLoadingTitle: "シンタックスハイライトを読み込み中",
|
|
31011
32509
|
syntaxErrorTitle: "シンタックスハイライトの読み込みに失敗",
|
|
31012
32510
|
syntaxOffTitle: "シンタックスハイライト無効",
|
|
31013
32511
|
hideTests: "test/spec ファイルを隠す",
|
|
32512
|
+
hideTestsLabel: "テスト非表示",
|
|
31014
32513
|
autoUpdate: "自動",
|
|
31015
32514
|
autoUpdateOnTitle: "ファイル変更時に自動更新",
|
|
31016
32515
|
autoUpdateOffTitle: "自動更新オフ — 手動で再読み込み"
|
|
31017
32516
|
},
|
|
32517
|
+
diff: {
|
|
32518
|
+
files: (count) => `${count}ファイル`,
|
|
32519
|
+
updated: (time) => `更新 ${time}`,
|
|
32520
|
+
updatedTitle: "最終更新",
|
|
32521
|
+
kindAdded: "追加",
|
|
32522
|
+
kindDeleted: "削除",
|
|
32523
|
+
kindRenamed: "名前変更",
|
|
32524
|
+
kindHeavy: "大容量",
|
|
32525
|
+
kindBinary: "バイナリ",
|
|
32526
|
+
kindMedia: "メディア",
|
|
32527
|
+
viewedProgress: (viewed, total) => `${viewed}/${total} 確認済み`,
|
|
32528
|
+
viewedProgressTitle: "確認進捗",
|
|
32529
|
+
nextUnviewed: "次の未確認",
|
|
32530
|
+
nextUnviewedTitle: "次の未確認ファイルへ移動 (n)",
|
|
32531
|
+
allViewed: "すべて確認済み",
|
|
32532
|
+
allViewedTitle: "表示中のファイルはすべて確認済みです",
|
|
32533
|
+
noChangesTitle: "変更はありません",
|
|
32534
|
+
noChangesBody: "この参照との差分はありません。",
|
|
32535
|
+
noChangesReload: "diff を更新",
|
|
32536
|
+
noChangesReloadTitle: "この差分範囲を再読み込み",
|
|
32537
|
+
noChangesHistory: "履歴を開く",
|
|
32538
|
+
noChangesHistoryTitle: "この範囲のコミット履歴を開く",
|
|
32539
|
+
emptyDiffTitle: "空の差分",
|
|
32540
|
+
emptyDiffBody: "このコミットは最初の親との差分がありません。",
|
|
32541
|
+
noCommitSelectedTitle: "コミット未選択",
|
|
32542
|
+
noCommitSelectedBody: "一覧からコミットを選ぶと変更内容を表示します。"
|
|
32543
|
+
},
|
|
31018
32544
|
changeBanner: {
|
|
31019
32545
|
text: "ファイルに変更がありました",
|
|
31020
32546
|
reload: "再読み込みする",
|
|
@@ -31034,14 +32560,56 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
31034
32560
|
view: "表示",
|
|
31035
32561
|
tree: "ツリー",
|
|
31036
32562
|
flat: "一覧",
|
|
32563
|
+
treeTitle: "ツリー表示",
|
|
32564
|
+
flatTitle: "一覧表示",
|
|
31037
32565
|
filter: "ファイル絞り込み… / ⌘K",
|
|
31038
32566
|
filterTitle: "ファイルを絞り込みます。/pattern/ は正規表現。/ でこの欄にフォーカス、Cmd/Ctrl+K で全ファイルパレット、Ctrl+G で grep、? でヘルプ。",
|
|
31039
|
-
|
|
32567
|
+
filterClear: "解除",
|
|
32568
|
+
filterClearTitle: "ファイル絞り込みを解除",
|
|
32569
|
+
hide: "サイドバーを隠す",
|
|
32570
|
+
show: "サイドバーを表示",
|
|
32571
|
+
repoTarget: "リポジトリの対象",
|
|
32572
|
+
openDirectoryInOs: "このフォルダをOSで開く",
|
|
32573
|
+
omittedHeavyLabel: "省略",
|
|
32574
|
+
omittedHeavyTitle: "ツリー展開は省略されていますが、詳細パネルでは開けます",
|
|
32575
|
+
omittedPrivateLabel: "非公開",
|
|
32576
|
+
omittedPrivateTitle: "このディレクトリはブラウザから開けません",
|
|
32577
|
+
commitEntryGitlinkLabel: "GIT",
|
|
32578
|
+
commitEntryGitlinkTitle: "Git のコミットに固定された参照です。フォルダではないため直接は開けません。",
|
|
32579
|
+
commitEntrySubmoduleLabel: "SUB",
|
|
32580
|
+
commitEntrySubmoduleTitle: "Git サブモジュール: 特定のコミットに固定されています。フォルダではないため直接は開けません。"
|
|
32581
|
+
},
|
|
32582
|
+
repo: {
|
|
32583
|
+
newFolder: "新規フォルダ",
|
|
32584
|
+
moveFolderToTrash: "フォルダをゴミ箱へ移動",
|
|
32585
|
+
uploadButton: "ファイルをアップロード",
|
|
32586
|
+
dropFilesInto: (target) => `${target} にファイルをドロップ`,
|
|
32587
|
+
uploadFailed: "アップロードに失敗しました",
|
|
32588
|
+
emptyDirectory: "このディレクトリにファイルはありません。",
|
|
32589
|
+
uploadConfirmTitle: "ファイルをアップロードしますか?",
|
|
32590
|
+
uploadConfirmBody: (count, target) => `${target} に ${count} 件のファイルをアップロードしますか?`,
|
|
32591
|
+
uploadConfirmLabel: "アップロード",
|
|
32592
|
+
sortName: "名前",
|
|
32593
|
+
sortUpdated: "更新日時",
|
|
32594
|
+
sortSize: "サイズ",
|
|
32595
|
+
repositoryFallback: "リポジトリ",
|
|
32596
|
+
repositoryRootFallback: "リポジトリのルート",
|
|
32597
|
+
gitlinkLabel: "固定コミット",
|
|
32598
|
+
gitlinkTitle: "特定のコミットに固定された参照です。この ref では直接開けません。",
|
|
32599
|
+
submoduleLabel: "サブモジュール",
|
|
32600
|
+
submoduleTitle: "Git サブモジュール: 特定のコミットに固定されています。直接は開けません。"
|
|
31040
32601
|
},
|
|
31041
32602
|
history: {
|
|
31042
32603
|
title: "コミット",
|
|
31043
32604
|
filter: "コミットを絞り込み...",
|
|
31044
|
-
filterTitle: "メッセージ、SHA、author:name、path:file でコミットを絞り込みます。"
|
|
32605
|
+
filterTitle: "メッセージ、SHA、author:name、path:file でコミットを絞り込みます。",
|
|
32606
|
+
refreshTitle: "コミット履歴を更新"
|
|
32607
|
+
},
|
|
32608
|
+
quickHelp: {
|
|
32609
|
+
buttonTitle: "クイックヘルプ(ショートカット)",
|
|
32610
|
+
panelTitle: "クイックヘルプ",
|
|
32611
|
+
close: "クイックヘルプを閉じる",
|
|
32612
|
+
viewAll: "すべてのキーバインドを見る →"
|
|
31045
32613
|
},
|
|
31046
32614
|
settings: {
|
|
31047
32615
|
title: "ビューア設定",
|
|
@@ -31117,6 +32685,8 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
31117
32685
|
});
|
|
31118
32686
|
setElementText(".global-help-link[data-route='help']", text2.nav.help);
|
|
31119
32687
|
setElementText(".product-label", text2.global.product);
|
|
32688
|
+
document.querySelector(".brand")?.setAttribute("aria-label", text2.global.brandHome);
|
|
32689
|
+
document.querySelector(".app-menu")?.setAttribute("aria-label", text2.global.menuViews);
|
|
31120
32690
|
const annotationsToggle = document.querySelector("#annotations-toggle");
|
|
31121
32691
|
if (annotationsToggle) {
|
|
31122
32692
|
annotationsToggle.title = text2.global.annotations;
|
|
@@ -31132,27 +32702,51 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
31132
32702
|
theme.title = text2.global.theme;
|
|
31133
32703
|
theme.setAttribute("aria-label", text2.global.theme);
|
|
31134
32704
|
}
|
|
32705
|
+
const quickHelpBtn = document.querySelector("#quick-help-btn");
|
|
32706
|
+
if (quickHelpBtn) {
|
|
32707
|
+
quickHelpBtn.title = text2.quickHelp.buttonTitle;
|
|
32708
|
+
quickHelpBtn.setAttribute("aria-label", text2.quickHelp.buttonTitle);
|
|
32709
|
+
}
|
|
32710
|
+
QUICK_HELP?.localize();
|
|
32711
|
+
const doctorTitle = doctorText(STATE.language).title;
|
|
32712
|
+
const doctorBtn = document.querySelector("#doctor-btn");
|
|
32713
|
+
if (doctorBtn) {
|
|
32714
|
+
doctorBtn.title = doctorTitle;
|
|
32715
|
+
doctorBtn.setAttribute("aria-label", doctorTitle);
|
|
32716
|
+
}
|
|
32717
|
+
document.querySelector("#doctor-sheet")?.setAttribute("aria-label", doctorTitle);
|
|
31135
32718
|
const copyAiContext = document.querySelector("#copy-ai-context");
|
|
31136
32719
|
if (copyAiContext) {
|
|
31137
32720
|
copyAiContext.title = text2.global.copyAiContext;
|
|
31138
32721
|
copyAiContext.setAttribute("aria-label", text2.global.copyAiContext);
|
|
32722
|
+
const copyAiContextLabel = copyAiContext.querySelector(".ai-context-label");
|
|
32723
|
+
if (copyAiContextLabel)
|
|
32724
|
+
copyAiContextLabel.textContent = text2.global.copyAiContextLabel;
|
|
31139
32725
|
}
|
|
31140
32726
|
const refReset = document.querySelector("#ref-reset");
|
|
31141
|
-
if (refReset)
|
|
32727
|
+
if (refReset) {
|
|
31142
32728
|
refReset.title = text2.topbar.resetRange;
|
|
32729
|
+
refReset.setAttribute("aria-label", text2.topbar.resetRange);
|
|
32730
|
+
}
|
|
31143
32731
|
const reload = document.querySelector("#reload-prom");
|
|
31144
|
-
if (reload)
|
|
32732
|
+
if (reload) {
|
|
31145
32733
|
reload.title = text2.topbar.reload;
|
|
32734
|
+
reload.setAttribute("aria-label", text2.topbar.reload);
|
|
32735
|
+
}
|
|
31146
32736
|
const layoutGroup = document.querySelector("#topbar .seg");
|
|
31147
32737
|
layoutGroup?.setAttribute("aria-label", text2.topbar.layout);
|
|
31148
32738
|
setElementText('#topbar .seg button[data-layout="line-by-line"]', text2.topbar.unified);
|
|
31149
32739
|
setElementText('#topbar .seg button[data-layout="side-by-side"]', text2.topbar.split);
|
|
31150
32740
|
const ignoreWs = document.querySelector("#ignore-ws");
|
|
31151
|
-
if (ignoreWs)
|
|
32741
|
+
if (ignoreWs) {
|
|
31152
32742
|
ignoreWs.title = text2.topbar.ignoreWs;
|
|
32743
|
+
ignoreWs.textContent = text2.topbar.ignoreWsLabel;
|
|
32744
|
+
}
|
|
31153
32745
|
const hideTests = document.querySelector("#hide-tests");
|
|
31154
|
-
if (hideTests)
|
|
32746
|
+
if (hideTests) {
|
|
31155
32747
|
hideTests.title = text2.topbar.hideTests;
|
|
32748
|
+
hideTests.textContent = text2.topbar.hideTestsLabel;
|
|
32749
|
+
}
|
|
31156
32750
|
applyAutoUpdateButton();
|
|
31157
32751
|
setHighlightButton(STATE.syntaxHighlight && getHljs() ? "loaded" : "idle");
|
|
31158
32752
|
setElementText(".sb-title", text2.sidebar.files);
|
|
@@ -31172,15 +32766,33 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
31172
32766
|
sbView?.setAttribute("aria-label", text2.sidebar.view);
|
|
31173
32767
|
setElementText('.sb-view-seg button[data-view="tree"]', text2.sidebar.tree);
|
|
31174
32768
|
setElementText('.sb-view-seg button[data-view="flat"]', text2.sidebar.flat);
|
|
32769
|
+
const sbViewTree = document.querySelector('.sb-view-seg button[data-view="tree"]');
|
|
32770
|
+
if (sbViewTree)
|
|
32771
|
+
sbViewTree.title = text2.sidebar.treeTitle;
|
|
32772
|
+
const sbViewFlat = document.querySelector('.sb-view-seg button[data-view="flat"]');
|
|
32773
|
+
if (sbViewFlat)
|
|
32774
|
+
sbViewFlat.title = text2.sidebar.flatTitle;
|
|
31175
32775
|
const filter = document.querySelector("#sb-filter");
|
|
31176
32776
|
if (filter) {
|
|
31177
32777
|
filter.placeholder = text2.sidebar.filter;
|
|
31178
32778
|
filter.title = text2.sidebar.filterTitle;
|
|
31179
32779
|
}
|
|
32780
|
+
const filterClear = document.querySelector("#sb-filter-clear");
|
|
32781
|
+
if (filterClear) {
|
|
32782
|
+
filterClear.textContent = text2.sidebar.filterClear;
|
|
32783
|
+
filterClear.title = text2.sidebar.filterClearTitle;
|
|
32784
|
+
filterClear.setAttribute("aria-label", text2.sidebar.filterClearTitle);
|
|
32785
|
+
}
|
|
32786
|
+
const repoTarget = document.querySelector("#repo-target");
|
|
32787
|
+
if (repoTarget) {
|
|
32788
|
+
repoTarget.title = text2.sidebar.repoTarget;
|
|
32789
|
+
repoTarget.setAttribute("aria-label", text2.sidebar.repoTarget);
|
|
32790
|
+
}
|
|
31180
32791
|
const sidebarToggle = document.querySelector("#sidebar-toggle");
|
|
31181
32792
|
if (sidebarToggle) {
|
|
31182
|
-
|
|
31183
|
-
sidebarToggle.
|
|
32793
|
+
const sidebarToggleTitle = STATE.sidebarHidden ? text2.sidebar.show : text2.sidebar.hide;
|
|
32794
|
+
sidebarToggle.title = sidebarToggleTitle;
|
|
32795
|
+
sidebarToggle.setAttribute("aria-label", sidebarToggleTitle);
|
|
31184
32796
|
}
|
|
31185
32797
|
setElementText(".sidebar-toggle-label", text2.sidebar.files);
|
|
31186
32798
|
setElementText(".history-title", text2.history.title);
|
|
@@ -31191,6 +32803,11 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
31191
32803
|
historyFilter.placeholder = text2.history.filter;
|
|
31192
32804
|
historyFilter.title = text2.history.filterTitle;
|
|
31193
32805
|
}
|
|
32806
|
+
document.querySelectorAll(".history-refresh").forEach((button) => {
|
|
32807
|
+
button.title = text2.history.refreshTitle;
|
|
32808
|
+
button.setAttribute("aria-label", text2.history.refreshTitle);
|
|
32809
|
+
});
|
|
32810
|
+
relocalizeHistory?.();
|
|
31194
32811
|
setElementText(".scope-settings-head strong", text2.settings.title);
|
|
31195
32812
|
const settingsClose = document.querySelector("#scope-settings-close");
|
|
31196
32813
|
settingsClose?.setAttribute("aria-label", text2.settings.close);
|
|
@@ -31259,7 +32876,9 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
31259
32876
|
setButtonLabel(document.querySelector("#query-history-panel-close"), text2.annotations.close);
|
|
31260
32877
|
relocalizeDatabase?.();
|
|
31261
32878
|
}
|
|
32879
|
+
let relocalizeHistory = null;
|
|
31262
32880
|
let relocalizeDatabase = null;
|
|
32881
|
+
let QUICK_HELP = null;
|
|
31263
32882
|
function setViewerLanguage(language, persist = true) {
|
|
31264
32883
|
const next = normalizeViewerLanguage(language);
|
|
31265
32884
|
STATE.language = next;
|
|
@@ -31286,6 +32905,13 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
31286
32905
|
el.classList.remove("live", "refreshing", "error");
|
|
31287
32906
|
if (s2)
|
|
31288
32907
|
el.classList.add(s2);
|
|
32908
|
+
const text2 = uiText();
|
|
32909
|
+
const label = s2 === "live" ? text2.global.statusLive : s2 === "refreshing" ? text2.global.statusLoading : s2 === "error" ? text2.global.statusError : text2.global.statusIdle;
|
|
32910
|
+
const labelEl = el.querySelector(".status-label");
|
|
32911
|
+
if (labelEl)
|
|
32912
|
+
labelEl.textContent = label;
|
|
32913
|
+
el.setAttribute("aria-label", label);
|
|
32914
|
+
updateNetworkActivity();
|
|
31289
32915
|
}
|
|
31290
32916
|
function applyTheme() {
|
|
31291
32917
|
document.documentElement.dataset.theme = STATE.theme;
|
|
@@ -31587,8 +33213,10 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
31587
33213
|
input.readOnly = true;
|
|
31588
33214
|
input.autocomplete = "off";
|
|
31589
33215
|
input.placeholder = options.placeholder;
|
|
31590
|
-
if (options.title)
|
|
33216
|
+
if (options.title) {
|
|
31591
33217
|
input.title = options.title;
|
|
33218
|
+
input.setAttribute("aria-label", options.title);
|
|
33219
|
+
}
|
|
31592
33220
|
if (options.value != null)
|
|
31593
33221
|
input.value = options.value;
|
|
31594
33222
|
const caret = document.createElement("span");
|
|
@@ -31692,7 +33320,8 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
31692
33320
|
currentRange,
|
|
31693
33321
|
setRoute,
|
|
31694
33322
|
setPreferredSourceTab: (tab) => SOURCE_VIEW.setPreferredSourceTab(tab),
|
|
31695
|
-
createFileBreadcrumb: (path, ref) => DIFF_VIEW.createFileBreadcrumb(path, ref)
|
|
33323
|
+
createFileBreadcrumb: (path, ref) => DIFF_VIEW.createFileBreadcrumb(path, ref),
|
|
33324
|
+
emptyText: () => uiText().diff
|
|
31696
33325
|
}, historyRoute);
|
|
31697
33326
|
activeFileHistoryDiffHost = mount.diffHost;
|
|
31698
33327
|
activeFileHistoryEmptyHost = mount.emptyHost;
|
|
@@ -31705,6 +33334,9 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
31705
33334
|
function withAnnotationSessionParam(rawUrl) {
|
|
31706
33335
|
return ANNOTATIONS_UI ? ANNOTATIONS_UI.withSessionParam(rawUrl) : rawUrl;
|
|
31707
33336
|
}
|
|
33337
|
+
function urlForRoute(route) {
|
|
33338
|
+
return withDoctorOverlay(withAnnotationSessionParam(buildRoute(route)), parseDoctorOverlay(window.location.pathname, window.location.search));
|
|
33339
|
+
}
|
|
31708
33340
|
function historyStateForRoute(route) {
|
|
31709
33341
|
return route.screen === "file" ? {
|
|
31710
33342
|
screen: "file",
|
|
@@ -31779,7 +33411,7 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
31779
33411
|
if (nextRoute.screen === "repo" || nextRoute.screen === "file" && (nextRoute.view === "blob" || nextRoute.view === "blame" || nextRoute.view === "history")) {
|
|
31780
33412
|
STATE.repoRef = nextRoute.ref || "worktree";
|
|
31781
33413
|
}
|
|
31782
|
-
const url =
|
|
33414
|
+
const url = urlForRoute(nextRoute);
|
|
31783
33415
|
const state = historyStateForRoute(nextRoute);
|
|
31784
33416
|
if (replace2)
|
|
31785
33417
|
history.replaceState(state, "", url);
|
|
@@ -32024,6 +33656,7 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
32024
33656
|
SERVER_GENERATION = generation;
|
|
32025
33657
|
},
|
|
32026
33658
|
invalidateRepoSidebar,
|
|
33659
|
+
diffText: () => uiText().diff,
|
|
32027
33660
|
getDiffRoot: () => activeFileHistoryDiffHost || $("#diff"),
|
|
32028
33661
|
getEmptyPane: () => activeFileHistoryEmptyHost || $("#empty"),
|
|
32029
33662
|
isEmbeddedDiffMode: () => !!activeFileHistoryDiffHost
|
|
@@ -32057,10 +33690,26 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
32057
33690
|
if (themeButton) {
|
|
32058
33691
|
themeButton.innerHTML = iconSvg("octicon-moon", MOON_16_PATH);
|
|
32059
33692
|
}
|
|
32060
|
-
const
|
|
32061
|
-
if (
|
|
32062
|
-
|
|
33693
|
+
const copyAiContextIcon = document.querySelector("#copy-ai-context .goi-icon");
|
|
33694
|
+
if (copyAiContextIcon) {
|
|
33695
|
+
copyAiContextIcon.innerHTML = iconSvg("octicon-copy", COPY_16_PATHS);
|
|
33696
|
+
}
|
|
33697
|
+
const autoUpdateIcon = document.querySelector("#auto-update .goi-icon");
|
|
33698
|
+
if (autoUpdateIcon) {
|
|
33699
|
+
autoUpdateIcon.innerHTML = iconSvg("octicon-sync", SYNC_16_PATH);
|
|
32063
33700
|
}
|
|
33701
|
+
const cancelRequestsIcon = document.querySelector("#cancel-requests .goi-icon");
|
|
33702
|
+
if (cancelRequestsIcon) {
|
|
33703
|
+
cancelRequestsIcon.innerHTML = iconSvg("octicon-x", X_16_PATH);
|
|
33704
|
+
}
|
|
33705
|
+
}
|
|
33706
|
+
function setRefActionIcons() {
|
|
33707
|
+
const refReset = document.querySelector("#ref-reset");
|
|
33708
|
+
if (refReset)
|
|
33709
|
+
refReset.innerHTML = iconSvg("octicon-x", X_16_PATH);
|
|
33710
|
+
const reload = document.querySelector("#reload-prom");
|
|
33711
|
+
if (reload)
|
|
33712
|
+
reload.innerHTML = iconSvg("octicon-sync", SYNC_16_PATH);
|
|
32064
33713
|
}
|
|
32065
33714
|
applySidebarFontSize();
|
|
32066
33715
|
applyCodeFontSize();
|
|
@@ -32070,6 +33719,7 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
32070
33719
|
hydrateRefSelectorMounts();
|
|
32071
33720
|
setSidebarTreeActionIcons();
|
|
32072
33721
|
setGlobalHeaderIcons();
|
|
33722
|
+
setRefActionIcons();
|
|
32073
33723
|
$$(".sb-view-seg button").forEach((b2) => {
|
|
32074
33724
|
b2.addEventListener("click", () => {
|
|
32075
33725
|
STATE.sbView = b2.dataset.view || "tree";
|
|
@@ -32100,11 +33750,15 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
32100
33750
|
};
|
|
32101
33751
|
}
|
|
32102
33752
|
}
|
|
33753
|
+
const databaseQuerySql = STATE.route.screen === "database" && STATE.route.tab === "query" ? document.querySelector(".db-container:not([hidden]) .db-query-editor:not([hidden]) .db-query-textarea")?.value : undefined;
|
|
32103
33754
|
const text2 = aiContextClipboardText({
|
|
32104
33755
|
route: STATE.route,
|
|
32105
33756
|
diffFrom: STATE.from,
|
|
32106
33757
|
diffTo: STATE.to,
|
|
32107
|
-
selectionCode
|
|
33758
|
+
selectionCode,
|
|
33759
|
+
diffMeta: window._lastMeta ? visibleDiffMetaForBrief(window._lastMeta) : null,
|
|
33760
|
+
viewedFiles: STATE.viewedFiles,
|
|
33761
|
+
databaseQuerySql
|
|
32108
33762
|
});
|
|
32109
33763
|
const finish = (ok, withCode, lineCount, reason) => {
|
|
32110
33764
|
const label = reason === "empty" ? uiText().global.copyAiContextEmpty : ok ? withCode ? uiText().global.copyAiContextCopiedWithCode(lineCount) : uiText().global.copyAiContextCopied : uiText().global.copyAiContextFailed;
|
|
@@ -32336,7 +33990,10 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
32336
33990
|
}
|
|
32337
33991
|
const sbFilter = $("#sb-filter");
|
|
32338
33992
|
if (sbFilter) {
|
|
32339
|
-
sbFilter.addEventListener("input", () =>
|
|
33993
|
+
sbFilter.addEventListener("input", () => {
|
|
33994
|
+
syncSidebarFilterClearButton();
|
|
33995
|
+
scheduleApplyFilter();
|
|
33996
|
+
});
|
|
32340
33997
|
sbFilter.addEventListener("keydown", (e2) => {
|
|
32341
33998
|
if (isImeComposing(e2))
|
|
32342
33999
|
return;
|
|
@@ -32351,6 +34008,7 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
32351
34008
|
} else if (e2.key === "Escape") {
|
|
32352
34009
|
if (sbFilter.value) {
|
|
32353
34010
|
sbFilter.value = "";
|
|
34011
|
+
syncSidebarFilterClearButton();
|
|
32354
34012
|
flushSidebarFilter();
|
|
32355
34013
|
applyFilter();
|
|
32356
34014
|
} else {
|
|
@@ -32359,6 +34017,11 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
32359
34017
|
}
|
|
32360
34018
|
});
|
|
32361
34019
|
}
|
|
34020
|
+
const sbFilterClear = document.querySelector("#sb-filter-clear");
|
|
34021
|
+
if (sbFilterClear) {
|
|
34022
|
+
syncSidebarFilterClearButton();
|
|
34023
|
+
sbFilterClear.addEventListener("click", clearSidebarFilter);
|
|
34024
|
+
}
|
|
32362
34025
|
function focusFileFilter() {
|
|
32363
34026
|
const input = $("#sb-filter");
|
|
32364
34027
|
input.focus();
|
|
@@ -32510,17 +34173,13 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
32510
34173
|
}));
|
|
32511
34174
|
return true;
|
|
32512
34175
|
}
|
|
34176
|
+
if (action === "next-unviewed-file") {
|
|
34177
|
+
if (DIFF_VIEW.scrollToNextUnviewedFile())
|
|
34178
|
+
scheduleMainSurfaceFocus();
|
|
34179
|
+
return true;
|
|
34180
|
+
}
|
|
32513
34181
|
if (action === "open-help") {
|
|
32514
|
-
|
|
32515
|
-
getRoute: () => STATE.route,
|
|
32516
|
-
getLanguage: () => STATE.language,
|
|
32517
|
-
currentRange,
|
|
32518
|
-
setRoute,
|
|
32519
|
-
setPageMode,
|
|
32520
|
-
renderHelpPage,
|
|
32521
|
-
setStatus,
|
|
32522
|
-
cancelActiveSourceLoad
|
|
32523
|
-
});
|
|
34182
|
+
QUICK_HELP?.toggle();
|
|
32524
34183
|
return true;
|
|
32525
34184
|
}
|
|
32526
34185
|
return false;
|
|
@@ -32573,6 +34232,103 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
32573
34232
|
if (window.location.pathname === "/") {
|
|
32574
34233
|
setRoute(STATE.route, true);
|
|
32575
34234
|
}
|
|
34235
|
+
function normalizedHistoryRefForEmptyDiff() {
|
|
34236
|
+
const candidate = STATE.to && STATE.to !== "worktree" ? STATE.to : STATE.from || "HEAD";
|
|
34237
|
+
return candidate && candidate !== "worktree" && !candidate.startsWith("--") ? candidate : "HEAD";
|
|
34238
|
+
}
|
|
34239
|
+
function emptyDiffHistoryRoute() {
|
|
34240
|
+
return {
|
|
34241
|
+
screen: "history",
|
|
34242
|
+
ref: normalizedHistoryRefForEmptyDiff(),
|
|
34243
|
+
range: currentRange()
|
|
34244
|
+
};
|
|
34245
|
+
}
|
|
34246
|
+
function setEmptyActionContent(action, iconName, iconPath, label, title) {
|
|
34247
|
+
action.title = title;
|
|
34248
|
+
action.setAttribute("aria-label", title);
|
|
34249
|
+
action.replaceChildren();
|
|
34250
|
+
const icon = document.createElement("span");
|
|
34251
|
+
icon.className = "empty-action-icon";
|
|
34252
|
+
icon.setAttribute("aria-hidden", "true");
|
|
34253
|
+
icon.innerHTML = iconSvg(iconName, iconPath);
|
|
34254
|
+
const text2 = document.createElement("span");
|
|
34255
|
+
text2.className = "empty-action-label";
|
|
34256
|
+
text2.textContent = label;
|
|
34257
|
+
action.append(icon, text2);
|
|
34258
|
+
}
|
|
34259
|
+
function navigateToEmptyDiffHistory(event) {
|
|
34260
|
+
if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)
|
|
34261
|
+
return;
|
|
34262
|
+
event.preventDefault();
|
|
34263
|
+
const route = emptyDiffHistoryRoute();
|
|
34264
|
+
history.pushState(historyStateForRoute(route), "", urlForRoute(route));
|
|
34265
|
+
window.scrollTo(0, 0);
|
|
34266
|
+
applyRouteFromLocation();
|
|
34267
|
+
}
|
|
34268
|
+
function ensureEmptyDiffActions(empty) {
|
|
34269
|
+
let actions = empty.querySelector(".empty-actions");
|
|
34270
|
+
if (actions)
|
|
34271
|
+
return actions;
|
|
34272
|
+
actions = document.createElement("div");
|
|
34273
|
+
actions.className = "empty-actions";
|
|
34274
|
+
actions.hidden = true;
|
|
34275
|
+
const reload = document.createElement("button");
|
|
34276
|
+
reload.type = "button";
|
|
34277
|
+
reload.className = "empty-action empty-action-primary";
|
|
34278
|
+
reload.dataset.emptyAction = "reload";
|
|
34279
|
+
reload.addEventListener("click", () => reloadDiffFromUi(reload));
|
|
34280
|
+
const historyLink = document.createElement("a");
|
|
34281
|
+
historyLink.className = "empty-action";
|
|
34282
|
+
historyLink.dataset.emptyAction = "history";
|
|
34283
|
+
historyLink.addEventListener("click", navigateToEmptyDiffHistory);
|
|
34284
|
+
actions.append(reload, historyLink);
|
|
34285
|
+
empty.appendChild(actions);
|
|
34286
|
+
return actions;
|
|
34287
|
+
}
|
|
34288
|
+
function syncEmptyDiffPane(empty, onHistory) {
|
|
34289
|
+
empty.classList.toggle("empty-with-actions", !onHistory);
|
|
34290
|
+
const text2 = uiText().diff;
|
|
34291
|
+
const h2 = empty.querySelector("h2");
|
|
34292
|
+
if (h2)
|
|
34293
|
+
h2.textContent = onHistory ? text2.emptyDiffTitle : text2.noChangesTitle;
|
|
34294
|
+
const p2 = empty.querySelector("p");
|
|
34295
|
+
if (p2)
|
|
34296
|
+
p2.textContent = onHistory ? text2.emptyDiffBody : text2.noChangesBody;
|
|
34297
|
+
const existingActions = empty.querySelector(".empty-actions");
|
|
34298
|
+
if (onHistory) {
|
|
34299
|
+
if (existingActions)
|
|
34300
|
+
existingActions.hidden = true;
|
|
34301
|
+
return;
|
|
34302
|
+
}
|
|
34303
|
+
const actions = ensureEmptyDiffActions(empty);
|
|
34304
|
+
const reload = actions.querySelector('[data-empty-action="reload"]');
|
|
34305
|
+
const historyLink = actions.querySelector('[data-empty-action="history"]');
|
|
34306
|
+
if (reload)
|
|
34307
|
+
setEmptyActionContent(reload, "octicon-sync", SYNC_16_PATH, text2.noChangesReload, text2.noChangesReloadTitle);
|
|
34308
|
+
if (historyLink) {
|
|
34309
|
+
const route = emptyDiffHistoryRoute();
|
|
34310
|
+
historyLink.href = urlForRoute(route);
|
|
34311
|
+
setEmptyActionContent(historyLink, "octicon-git-branch", GIT_BRANCH_16_PATH, text2.noChangesHistory, text2.noChangesHistoryTitle);
|
|
34312
|
+
}
|
|
34313
|
+
actions.hidden = false;
|
|
34314
|
+
}
|
|
34315
|
+
function reloadDiffFromUi(trigger) {
|
|
34316
|
+
const topbarButton = $("#reload-prom");
|
|
34317
|
+
topbarButton.classList.add("spinning");
|
|
34318
|
+
if (trigger && trigger !== topbarButton) {
|
|
34319
|
+
trigger.classList.add("spinning");
|
|
34320
|
+
trigger.setAttribute("aria-busy", "true");
|
|
34321
|
+
}
|
|
34322
|
+
load().finally(() => {
|
|
34323
|
+
setTimeout(() => {
|
|
34324
|
+
topbarButton.classList.remove("spinning");
|
|
34325
|
+
if (trigger && trigger !== topbarButton) {
|
|
34326
|
+
trigger.classList.remove("spinning");
|
|
34327
|
+
trigger.setAttribute("aria-busy", "false");
|
|
34328
|
+
}
|
|
34329
|
+
}, 200);
|
|
34330
|
+
});
|
|
34331
|
+
}
|
|
32576
34332
|
function load(options = {}) {
|
|
32577
34333
|
if (STATE.route.screen === "help") {
|
|
32578
34334
|
setStatus("live");
|
|
@@ -32598,12 +34354,7 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
32598
34354
|
const empty = activeFileHistoryEmptyHost || $("#empty");
|
|
32599
34355
|
if (empty) {
|
|
32600
34356
|
const onHistory = STATE.route.screen === "history" || isFileHistoryRoute(STATE.route);
|
|
32601
|
-
|
|
32602
|
-
if (h2)
|
|
32603
|
-
h2.textContent = onHistory ? "Empty diff" : "No changes";
|
|
32604
|
-
const p2 = empty.querySelector("p");
|
|
32605
|
-
if (p2)
|
|
32606
|
-
p2.textContent = onHistory ? "This commit has no changes against its first parent." : "The working tree is clean against this ref.";
|
|
34357
|
+
syncEmptyDiffPane(empty, onHistory);
|
|
32607
34358
|
}
|
|
32608
34359
|
}
|
|
32609
34360
|
const routeAtRequest = STATE.route;
|
|
@@ -32716,12 +34467,13 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
32716
34467
|
DIFF_VIEW.clearLoadQueue();
|
|
32717
34468
|
if (activeFileHistoryEmptyHost) {
|
|
32718
34469
|
activeFileHistoryEmptyHost.classList.remove("hidden");
|
|
34470
|
+
const text2 = uiText().diff;
|
|
32719
34471
|
const h2 = activeFileHistoryEmptyHost.querySelector("h2");
|
|
32720
34472
|
if (h2)
|
|
32721
|
-
h2.textContent =
|
|
34473
|
+
h2.textContent = text2.noCommitSelectedTitle;
|
|
32722
34474
|
const p2 = activeFileHistoryEmptyHost.querySelector("p");
|
|
32723
34475
|
if (p2)
|
|
32724
|
-
p2.textContent =
|
|
34476
|
+
p2.textContent = text2.noCommitSelectedBody;
|
|
32725
34477
|
}
|
|
32726
34478
|
setStatus("live");
|
|
32727
34479
|
return;
|
|
@@ -32740,13 +34492,32 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
32740
34492
|
invalidateRepoSidebar,
|
|
32741
34493
|
clearLoadQueue: () => DIFF_VIEW.clearLoadQueue(),
|
|
32742
34494
|
placeSidebarToggle,
|
|
32743
|
-
setStatus
|
|
34495
|
+
setStatus,
|
|
34496
|
+
emptyText: () => uiText().diff
|
|
32744
34497
|
});
|
|
32745
34498
|
},
|
|
32746
34499
|
getSyntaxHighlight: () => STATE.syntaxHighlight,
|
|
32747
34500
|
getLanguage: () => STATE.language,
|
|
32748
34501
|
trackLoad
|
|
32749
34502
|
});
|
|
34503
|
+
relocalizeHistory = () => HISTORY_VIEW.localize();
|
|
34504
|
+
QUICK_HELP = createQuickHelp({
|
|
34505
|
+
$,
|
|
34506
|
+
getLanguage: () => STATE.language,
|
|
34507
|
+
getText: () => uiText().quickHelp,
|
|
34508
|
+
openFullKeybindings: () => {
|
|
34509
|
+
openHelpKeybindings({
|
|
34510
|
+
getRoute: () => STATE.route,
|
|
34511
|
+
getLanguage: () => STATE.language,
|
|
34512
|
+
currentRange,
|
|
34513
|
+
setRoute,
|
|
34514
|
+
setPageMode,
|
|
34515
|
+
renderHelpPage,
|
|
34516
|
+
setStatus,
|
|
34517
|
+
cancelActiveSourceLoad
|
|
34518
|
+
});
|
|
34519
|
+
}
|
|
34520
|
+
});
|
|
32750
34521
|
const DOCTOR_VIEW = createDoctorView({
|
|
32751
34522
|
$: (sel) => document.querySelector(sel),
|
|
32752
34523
|
escapeHtml: escapeHtml3,
|
|
@@ -32968,13 +34739,7 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
32968
34739
|
});
|
|
32969
34740
|
if (STATE.syntaxHighlight)
|
|
32970
34741
|
setSyntaxHighlight(true, false);
|
|
32971
|
-
$("#reload-prom").addEventListener("click", () =>
|
|
32972
|
-
const btn = $("#reload-prom");
|
|
32973
|
-
btn.classList.add("spinning");
|
|
32974
|
-
load().finally(() => {
|
|
32975
|
-
setTimeout(() => btn.classList.remove("spinning"), 200);
|
|
32976
|
-
});
|
|
32977
|
-
});
|
|
34742
|
+
$("#reload-prom").addEventListener("click", () => reloadDiffFromUi());
|
|
32978
34743
|
function applyHideTests() {
|
|
32979
34744
|
const btn = $("#hide-tests");
|
|
32980
34745
|
if (btn)
|
|
@@ -32996,26 +34761,34 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
32996
34761
|
applyViewedState();
|
|
32997
34762
|
applyHideTestsToMeta();
|
|
32998
34763
|
}
|
|
32999
|
-
function
|
|
33000
|
-
|
|
33001
|
-
|
|
33002
|
-
return;
|
|
34764
|
+
function visibleDiffMetaForBrief(meta) {
|
|
34765
|
+
if (!meta.totals)
|
|
34766
|
+
return meta;
|
|
33003
34767
|
const effective = STATE.hideTests && !isRepositorySidebarMode();
|
|
33004
|
-
if (!effective)
|
|
33005
|
-
|
|
33006
|
-
return;
|
|
33007
|
-
}
|
|
34768
|
+
if (!effective)
|
|
34769
|
+
return meta;
|
|
33008
34770
|
let additions = 0;
|
|
33009
34771
|
let deletions = 0;
|
|
33010
|
-
|
|
33011
|
-
for (const f2 of
|
|
34772
|
+
const visibleFiles = [];
|
|
34773
|
+
for (const f2 of meta.files) {
|
|
33012
34774
|
if (TEST_RE.test(f2.path || ""))
|
|
33013
34775
|
continue;
|
|
33014
34776
|
additions += f2.additions || 0;
|
|
33015
34777
|
deletions += f2.deletions || 0;
|
|
33016
|
-
|
|
34778
|
+
visibleFiles.push(f2);
|
|
33017
34779
|
}
|
|
33018
|
-
|
|
34780
|
+
return {
|
|
34781
|
+
...meta,
|
|
34782
|
+
files: visibleFiles,
|
|
34783
|
+
totals: { files: visibleFiles.length, additions, deletions }
|
|
34784
|
+
};
|
|
34785
|
+
}
|
|
34786
|
+
function applyHideTestsToMeta() {
|
|
34787
|
+
const meta = window._lastMeta;
|
|
34788
|
+
if (!meta?.totals)
|
|
34789
|
+
return;
|
|
34790
|
+
renderMeta(visibleDiffMetaForBrief(meta));
|
|
34791
|
+
applyViewedState();
|
|
33019
34792
|
}
|
|
33020
34793
|
applyHideTests();
|
|
33021
34794
|
$("#hide-tests").addEventListener("click", () => {
|
|
@@ -33154,9 +34927,13 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
33154
34927
|
return;
|
|
33155
34928
|
const text2 = uiText();
|
|
33156
34929
|
btn.classList.toggle("active", STATE.autoUpdate);
|
|
33157
|
-
|
|
33158
|
-
btn.title =
|
|
34930
|
+
const autoUpdateTitle = STATE.autoUpdate ? text2.topbar.autoUpdateOnTitle : text2.topbar.autoUpdateOffTitle;
|
|
34931
|
+
btn.title = autoUpdateTitle;
|
|
34932
|
+
btn.setAttribute("aria-label", autoUpdateTitle);
|
|
33159
34933
|
btn.setAttribute("aria-pressed", STATE.autoUpdate ? "true" : "false");
|
|
34934
|
+
const label = btn.querySelector(".auto-update-label");
|
|
34935
|
+
if (label)
|
|
34936
|
+
label.textContent = text2.topbar.autoUpdate;
|
|
33160
34937
|
}
|
|
33161
34938
|
function setAutoUpdate(on) {
|
|
33162
34939
|
STATE.autoUpdate = on;
|
|
@@ -33359,6 +35136,8 @@ code-viewer query snapshot delete --id snap-abc123`
|
|
|
33359
35136
|
paths = parsed.paths;
|
|
33360
35137
|
} catch {}
|
|
33361
35138
|
}
|
|
35139
|
+
if (isHistoryPanelRoute(STATE.route))
|
|
35140
|
+
HISTORY_VIEW.notePossibleUpdate();
|
|
33362
35141
|
scheduleSseLoad(paths);
|
|
33363
35142
|
});
|
|
33364
35143
|
es.addEventListener("watch-limit", (event) => {
|