collabmd 0.1.31 → 0.1.32
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/dist/client/assets/{drawio-editor-B4sHHwWJ.js → drawio-editor-Br4qyh3r.js} +1 -1
- package/dist/client/assets/drawioEditor-ClmnTx5J.js +2 -0
- package/dist/client/assets/{editor-session-BKHEYkbY.js → editor-session-Cf-iV5-3.js} +2 -2
- package/dist/client/assets/embedded-editor-base-CgEkjNYn.css +1 -0
- package/dist/client/assets/{excalidraw-editor-CHbeNZu6.js → excalidraw-editor-CXAxVhlw.js} +2 -2
- package/dist/client/assets/{excalidrawEditor-BhaTX2Ko.js → excalidrawEditor-DoH_kMdu.js} +2 -2
- package/dist/client/assets/exportDocument-9wTrBZNS.css +1 -0
- package/dist/client/assets/{index-kPgEYvEX.js → index-C8QZYHvV.js} +2 -2
- package/dist/client/assets/index-CxSbUTs2.css +1 -0
- package/dist/client/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- package/dist/client/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- package/dist/client/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- package/dist/client/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- package/dist/client/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/dist/client/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/dist/client/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
- package/dist/client/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
- package/dist/client/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
- package/dist/client/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
- package/dist/client/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
- package/dist/client/assets/main-BjHHMlv0.js +1249 -0
- package/dist/client/assets/vault-api-client-Bf9tB_GW.js +1 -0
- package/dist/client/assets/vault-api-client-D7Ck0CvR.css +1 -0
- package/dist/client/drawio-editor.html +1 -1
- package/dist/client/excalidraw-editor.html +1 -1
- package/dist/client/export-document.html +2 -2
- package/dist/client/index.html +2 -2
- package/package.json +4 -1
- package/src/client/app/main-entry.js +2 -0
- package/src/client/application/app-shell/git-feature.js +28 -36
- package/src/client/application/app-shell/presence-feature.js +3 -1
- package/src/client/application/diagram-preview-hydrator.js +24 -15
- package/src/client/application/mermaid-preview-hydrator.js +121 -4
- package/src/client/application/plantuml-preview-hydrator.js +6 -16
- package/src/client/application/preview-renderer.js +11 -2
- package/src/client/bootstrap/collabmd-app-shell.js +176 -50
- package/src/client/domain/excalidraw-document-switch.js +3 -0
- package/src/client/excalidraw-editor.js +187 -84
- package/src/client/infrastructure/auth-client.js +4 -4
- package/src/client/infrastructure/backlinks-api-client.js +18 -0
- package/src/client/infrastructure/comment-thread-store.js +4 -0
- package/src/client/infrastructure/editor-session.js +2 -0
- package/src/client/infrastructure/git-api-client.js +134 -0
- package/src/client/infrastructure/plantuml-api-client.js +21 -0
- package/src/client/infrastructure/vault-api-client.js +67 -0
- package/src/client/presentation/backlinks-panel.js +6 -9
- package/src/client/presentation/bases-preview-controller.js +26 -7
- package/src/client/presentation/excalidraw-embed-controller.js +251 -15
- package/src/client/presentation/excalidraw-embed-reconciler.js +0 -1
- package/src/client/presentation/file-action-controller.js +97 -0
- package/src/client/presentation/file-explorer-controller.js +2 -0
- package/src/client/presentation/file-explorer-view.js +368 -0
- package/src/client/presentation/file-history-view-controller.js +41 -40
- package/src/client/presentation/git-diff-view-controller.js +70 -53
- package/src/client/presentation/git-panel-controller.js +12 -30
- package/src/client/styles/export-document.css +45 -2
- package/src/client/styles/features/auth-gate.css +13 -24
- package/src/client/styles/features/comment-card.css +6 -0
- package/src/client/styles/features/comments-drawer.css +38 -18
- package/src/client/styles/features/diagram-preview.css +33 -0
- package/src/client/styles/features/embedded-preview.css +37 -11
- package/src/client/styles/features/preview-markdown.css +103 -28
- package/src/client/styles/foundation/themes.css +4 -0
- package/src/client/styles/foundation/tokens.css +4 -3
- package/src/client/styles/layout/sidebar.css +72 -0
- package/src/server/auth/auth-common.js +224 -0
- package/src/server/auth/auth-constants.js +30 -0
- package/src/server/auth/auth-strategies.js +320 -0
- package/src/server/auth/create-auth-service.js +24 -545
- package/src/server/domain/bases/base-definition.js +255 -0
- package/src/server/domain/bases/base-expression-runtime.js +1159 -0
- package/src/server/domain/bases/base-index-snapshot-store.js +418 -0
- package/src/server/domain/bases/base-query-results.js +205 -0
- package/src/server/domain/bases/base-query-service.js +68 -1965
- package/src/server/domain/collaboration/collaboration-room.js +36 -1
- package/src/server/domain/collaboration/room-client-state-store.js +1 -0
- package/src/server/domain/collaboration/room-persistence-controller.js +1 -1
- package/src/server/infrastructure/http/create-vault-api-query-handler.js +109 -1
- package/src/server/infrastructure/http/http-response.js +56 -0
- package/src/server/infrastructure/persistence/vault-file-store.js +110 -0
- package/dist/client/assets/drawioEditor-DGpo2hcx.js +0 -2
- package/dist/client/assets/embedded-editor-base-DgmRcsR8.css +0 -1
- package/dist/client/assets/exportDocument-DmV7Gngb.css +0 -1
- package/dist/client/assets/index-D69HOZHr.css +0 -1
- package/dist/client/assets/main-DSxNTtD-.js +0 -1243
- package/dist/client/assets/vault-api-client-BzHQseMN.js +0 -1
- package/dist/client/assets/vault-api-client-De7kMvrE.css +0 -1
- /package/dist/client/assets/{exportDocument-CtZKWE2c.js → exportDocument-Bia2hI25.js} +0 -0
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { escapeHtml } from '../domain/vault-utils.js';
|
|
2
|
-
import { resolveApiUrl } from '../domain/runtime-paths.js';
|
|
3
2
|
import { buttonClassNames } from './components/ui/button.js';
|
|
4
3
|
|
|
5
4
|
const HISTORY_PAGE_SIZE = 30;
|
|
@@ -62,6 +61,7 @@ function createEmptyHistoryState() {
|
|
|
62
61
|
export class FileHistoryViewController {
|
|
63
62
|
constructor({
|
|
64
63
|
diffRenderer = null,
|
|
64
|
+
gitApiClient = null,
|
|
65
65
|
onOpenCommitDiff = () => {},
|
|
66
66
|
onOpenFile = () => {},
|
|
67
67
|
onOpenPreview = () => {},
|
|
@@ -69,6 +69,7 @@ export class FileHistoryViewController {
|
|
|
69
69
|
toastController = null,
|
|
70
70
|
} = {}) {
|
|
71
71
|
this.diffRenderer = diffRenderer;
|
|
72
|
+
this.gitApiClient = gitApiClient;
|
|
72
73
|
this.onOpenCommitDiff = onOpenCommitDiff;
|
|
73
74
|
this.onOpenFile = onOpenFile;
|
|
74
75
|
this.onOpenPreview = onOpenPreview;
|
|
@@ -89,6 +90,7 @@ export class FileHistoryViewController {
|
|
|
89
90
|
this.nextButton = document.getElementById('diffNextBtn');
|
|
90
91
|
this.layoutToggle = document.getElementById('diffLayoutToggle');
|
|
91
92
|
this.modeButtons = Array.from(document.querySelectorAll('[data-diff-mode]'));
|
|
93
|
+
this.isActive = false;
|
|
92
94
|
this.currentFilePath = null;
|
|
93
95
|
this.localChanges = null;
|
|
94
96
|
this.history = createEmptyHistoryState();
|
|
@@ -104,6 +106,9 @@ export class FileHistoryViewController {
|
|
|
104
106
|
|
|
105
107
|
initialize() {
|
|
106
108
|
this.openEditorButton?.addEventListener('click', () => {
|
|
109
|
+
if (!this.isActive) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
107
112
|
if (!this.currentFilePath) {
|
|
108
113
|
return;
|
|
109
114
|
}
|
|
@@ -113,6 +118,9 @@ export class FileHistoryViewController {
|
|
|
113
118
|
|
|
114
119
|
this.modeButtons.forEach((button) => {
|
|
115
120
|
button.addEventListener('click', () => {
|
|
121
|
+
if (!this.isActive) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
116
124
|
const nextMode = button.getAttribute('data-diff-mode');
|
|
117
125
|
if (!nextMode || nextMode === this.diffMode) {
|
|
118
126
|
return;
|
|
@@ -123,6 +131,9 @@ export class FileHistoryViewController {
|
|
|
123
131
|
});
|
|
124
132
|
|
|
125
133
|
this.content?.addEventListener('click', (event) => {
|
|
134
|
+
if (!this.isActive) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
126
137
|
const selectionButton = event.target instanceof Element
|
|
127
138
|
? event.target.closest('[data-file-history-select]')
|
|
128
139
|
: null;
|
|
@@ -160,6 +171,7 @@ export class FileHistoryViewController {
|
|
|
160
171
|
}
|
|
161
172
|
|
|
162
173
|
hide() {
|
|
174
|
+
this.isActive = false;
|
|
163
175
|
this.page?.classList.add('hidden');
|
|
164
176
|
this.content?.classList.remove('diff-content--history');
|
|
165
177
|
if (this.content) {
|
|
@@ -175,7 +187,6 @@ export class FileHistoryViewController {
|
|
|
175
187
|
this.historyListElement = null;
|
|
176
188
|
this.historyListScrollTop = 0;
|
|
177
189
|
this.selectionRequestToken = 0;
|
|
178
|
-
this.syncToolbar();
|
|
179
190
|
}
|
|
180
191
|
|
|
181
192
|
getEntries() {
|
|
@@ -229,6 +240,7 @@ export class FileHistoryViewController {
|
|
|
229
240
|
}
|
|
230
241
|
|
|
231
242
|
async openFileHistory({ filePath }) {
|
|
243
|
+
this.isActive = true;
|
|
232
244
|
this.currentFilePath = String(filePath ?? '').trim() || null;
|
|
233
245
|
this.localChanges = null;
|
|
234
246
|
this.history = {
|
|
@@ -289,16 +301,11 @@ export class FileHistoryViewController {
|
|
|
289
301
|
return null;
|
|
290
302
|
}
|
|
291
303
|
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
const data = await response.json();
|
|
298
|
-
if (!response.ok) {
|
|
299
|
-
throw new Error(data.error || 'Failed to load local file changes');
|
|
300
|
-
}
|
|
301
|
-
|
|
304
|
+
const data = await this.gitApiClient.readDiff({
|
|
305
|
+
metaOnly: true,
|
|
306
|
+
path: this.currentFilePath,
|
|
307
|
+
scope: 'all',
|
|
308
|
+
});
|
|
302
309
|
const file = data.files?.[0];
|
|
303
310
|
if (!file) {
|
|
304
311
|
return null;
|
|
@@ -322,16 +329,11 @@ export class FileHistoryViewController {
|
|
|
322
329
|
};
|
|
323
330
|
}
|
|
324
331
|
|
|
325
|
-
const
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
const data = await response.json();
|
|
331
|
-
if (!response.ok) {
|
|
332
|
-
throw new Error(data.error || 'Failed to load file history');
|
|
333
|
-
}
|
|
334
|
-
|
|
332
|
+
const data = await this.gitApiClient.readFileHistory({
|
|
333
|
+
limit: HISTORY_PAGE_SIZE,
|
|
334
|
+
offset,
|
|
335
|
+
path: this.currentFilePath,
|
|
336
|
+
});
|
|
335
337
|
const commits = Array.isArray(data.commits) ? data.commits : [];
|
|
336
338
|
return {
|
|
337
339
|
commits,
|
|
@@ -350,30 +352,20 @@ export class FileHistoryViewController {
|
|
|
350
352
|
}
|
|
351
353
|
|
|
352
354
|
if (entry.type === 'local') {
|
|
353
|
-
const
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
const data = await response.json();
|
|
358
|
-
if (!response.ok) {
|
|
359
|
-
throw new Error(data.error || 'Failed to load local diff');
|
|
360
|
-
}
|
|
361
|
-
|
|
355
|
+
const data = await this.gitApiClient.readDiff({
|
|
356
|
+
path: this.currentFilePath || '',
|
|
357
|
+
scope: 'all',
|
|
358
|
+
});
|
|
362
359
|
return {
|
|
363
360
|
detail: data.files?.[0] ?? null,
|
|
364
361
|
summary: data.summary ?? entry.summary ?? null,
|
|
365
362
|
};
|
|
366
363
|
}
|
|
367
364
|
|
|
368
|
-
const
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
const data = await response.json();
|
|
373
|
-
if (!response.ok) {
|
|
374
|
-
throw new Error(data.error || 'Failed to load commit diff');
|
|
375
|
-
}
|
|
376
|
-
|
|
365
|
+
const data = await this.gitApiClient.readCommit({
|
|
366
|
+
hash: entry.hash || '',
|
|
367
|
+
path: entry.pathAtCommit || '',
|
|
368
|
+
});
|
|
377
369
|
return {
|
|
378
370
|
commit: data.commit ?? null,
|
|
379
371
|
detail: data.files?.[0] ?? null,
|
|
@@ -564,6 +556,9 @@ export class FileHistoryViewController {
|
|
|
564
556
|
}
|
|
565
557
|
|
|
566
558
|
renderLoading() {
|
|
559
|
+
if (!this.isActive) {
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
567
562
|
this.page?.classList.remove('hidden');
|
|
568
563
|
if (this.content) {
|
|
569
564
|
this.content.classList.add('diff-content--history');
|
|
@@ -574,6 +569,9 @@ export class FileHistoryViewController {
|
|
|
574
569
|
}
|
|
575
570
|
|
|
576
571
|
renderEmpty(message) {
|
|
572
|
+
if (!this.isActive) {
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
577
575
|
this.page?.classList.remove('hidden');
|
|
578
576
|
if (this.content) {
|
|
579
577
|
this.content.classList.add('diff-content--history');
|
|
@@ -744,6 +742,9 @@ export class FileHistoryViewController {
|
|
|
744
742
|
}
|
|
745
743
|
|
|
746
744
|
render() {
|
|
745
|
+
if (!this.isActive) {
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
747
748
|
this.page?.classList.remove('hidden');
|
|
748
749
|
this.captureListScroll();
|
|
749
750
|
this.syncToolbar();
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { escapeHtml } from '../domain/vault-utils.js';
|
|
2
|
-
import { resolveApiUrl } from '../domain/runtime-paths.js';
|
|
3
2
|
import { buttonClassNames } from './components/ui/button.js';
|
|
4
3
|
|
|
5
4
|
function getPathLeaf(pathValue) {
|
|
@@ -146,6 +145,7 @@ function renderSplitRow(leftLine, rightLine) {
|
|
|
146
145
|
|
|
147
146
|
export class GitDiffViewController {
|
|
148
147
|
constructor({
|
|
148
|
+
gitApiClient = null,
|
|
149
149
|
onBackToHistory = null,
|
|
150
150
|
onCommitStaged = null,
|
|
151
151
|
onOpenFile = null,
|
|
@@ -153,6 +153,7 @@ export class GitDiffViewController {
|
|
|
153
153
|
onUnstageFile = null,
|
|
154
154
|
toastController = null,
|
|
155
155
|
} = {}) {
|
|
156
|
+
this.gitApiClient = gitApiClient;
|
|
156
157
|
this.onBackToHistory = onBackToHistory;
|
|
157
158
|
this.onCommitStaged = onCommitStaged;
|
|
158
159
|
this.onOpenFile = onOpenFile;
|
|
@@ -176,6 +177,7 @@ export class GitDiffViewController {
|
|
|
176
177
|
this.layoutToggle = document.getElementById('diffLayoutToggle');
|
|
177
178
|
this.modeButtons = Array.from(document.querySelectorAll('[data-diff-mode]'));
|
|
178
179
|
this.layoutButtons = Array.from(document.querySelectorAll('[data-diff-layout]'));
|
|
180
|
+
this.isActive = false;
|
|
179
181
|
this.mode = 'unified';
|
|
180
182
|
this.layoutMode = 'focused';
|
|
181
183
|
this.source = 'workspace';
|
|
@@ -196,9 +198,22 @@ export class GitDiffViewController {
|
|
|
196
198
|
}
|
|
197
199
|
|
|
198
200
|
initialize() {
|
|
199
|
-
this.prevButton?.addEventListener('click', () =>
|
|
200
|
-
|
|
201
|
+
this.prevButton?.addEventListener('click', () => {
|
|
202
|
+
if (!this.isActive) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
this.navigateFile(-1);
|
|
206
|
+
});
|
|
207
|
+
this.nextButton?.addEventListener('click', () => {
|
|
208
|
+
if (!this.isActive) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
this.navigateFile(1);
|
|
212
|
+
});
|
|
201
213
|
this.backToHistoryButton?.addEventListener('click', () => {
|
|
214
|
+
if (!this.isActive) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
202
217
|
if (!this.commitMeta?.hash) {
|
|
203
218
|
return;
|
|
204
219
|
}
|
|
@@ -208,6 +223,9 @@ export class GitDiffViewController {
|
|
|
208
223
|
});
|
|
209
224
|
});
|
|
210
225
|
this.openEditorButton?.addEventListener('click', () => {
|
|
226
|
+
if (!this.isActive) {
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
211
229
|
if (this.source !== 'workspace') {
|
|
212
230
|
return;
|
|
213
231
|
}
|
|
@@ -220,6 +238,9 @@ export class GitDiffViewController {
|
|
|
220
238
|
this.onOpenFile?.(currentFile.path);
|
|
221
239
|
});
|
|
222
240
|
this.primaryActionButton?.addEventListener('click', () => {
|
|
241
|
+
if (!this.isActive) {
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
223
244
|
const action = this.getPrimaryAction();
|
|
224
245
|
if (!action) {
|
|
225
246
|
return;
|
|
@@ -228,9 +249,15 @@ export class GitDiffViewController {
|
|
|
228
249
|
void this.handleFileAction(action);
|
|
229
250
|
});
|
|
230
251
|
this.commitButton?.addEventListener('click', () => {
|
|
252
|
+
if (!this.isActive) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
231
255
|
void this.handleFileAction('commit');
|
|
232
256
|
});
|
|
233
257
|
this.content?.addEventListener('click', (event) => {
|
|
258
|
+
if (!this.isActive) {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
234
261
|
const loadButton = event.target instanceof Element
|
|
235
262
|
? event.target.closest('[data-load-full-diff]')
|
|
236
263
|
: null;
|
|
@@ -265,6 +292,9 @@ export class GitDiffViewController {
|
|
|
265
292
|
});
|
|
266
293
|
this.modeButtons.forEach((button) => {
|
|
267
294
|
button.addEventListener('click', () => {
|
|
295
|
+
if (!this.isActive) {
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
268
298
|
const nextMode = button.getAttribute('data-diff-mode');
|
|
269
299
|
if (!nextMode || nextMode === this.mode) {
|
|
270
300
|
return;
|
|
@@ -275,6 +305,9 @@ export class GitDiffViewController {
|
|
|
275
305
|
});
|
|
276
306
|
this.layoutButtons.forEach((button) => {
|
|
277
307
|
button.addEventListener('click', () => {
|
|
308
|
+
if (!this.isActive) {
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
278
311
|
const nextLayout = button.getAttribute('data-diff-layout');
|
|
279
312
|
if (!nextLayout || nextLayout === this.layoutMode) {
|
|
280
313
|
return;
|
|
@@ -283,11 +316,15 @@ export class GitDiffViewController {
|
|
|
283
316
|
});
|
|
284
317
|
});
|
|
285
318
|
this.scrollContainer?.addEventListener('scroll', () => {
|
|
319
|
+
if (!this.isActive) {
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
286
322
|
this.handleScrollSelection();
|
|
287
323
|
});
|
|
288
324
|
}
|
|
289
325
|
|
|
290
326
|
hide() {
|
|
327
|
+
this.isActive = false;
|
|
291
328
|
this.page?.classList.add('hidden');
|
|
292
329
|
if (this.content) {
|
|
293
330
|
this.content.innerHTML = '';
|
|
@@ -308,10 +345,10 @@ export class GitDiffViewController {
|
|
|
308
345
|
this.historyFilePath = null;
|
|
309
346
|
this.pendingAction = null;
|
|
310
347
|
this.repoStatus = null;
|
|
311
|
-
this.syncToolbar();
|
|
312
348
|
}
|
|
313
349
|
|
|
314
350
|
async openWorkspaceDiff({ filePath = null, scope = 'all' } = {}) {
|
|
351
|
+
this.isActive = true;
|
|
315
352
|
this.source = 'workspace';
|
|
316
353
|
this.layoutMode = 'focused';
|
|
317
354
|
this.commitHash = null;
|
|
@@ -327,19 +364,11 @@ export class GitDiffViewController {
|
|
|
327
364
|
this.renderLoading('Loading diff summary...');
|
|
328
365
|
|
|
329
366
|
try {
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
}
|
|
335
|
-
query.set('metaOnly', 'true');
|
|
336
|
-
|
|
337
|
-
const response = await fetch(resolveApiUrl(`/git/diff?${query.toString()}`));
|
|
338
|
-
const data = await response.json();
|
|
339
|
-
if (!response.ok) {
|
|
340
|
-
throw new Error(data.error || 'Failed to load git diff');
|
|
341
|
-
}
|
|
342
|
-
|
|
367
|
+
const data = await this.gitApiClient.readDiff({
|
|
368
|
+
metaOnly: true,
|
|
369
|
+
path: filePath,
|
|
370
|
+
scope,
|
|
371
|
+
});
|
|
343
372
|
this.data = data;
|
|
344
373
|
const initialIndex = filePath
|
|
345
374
|
? Math.max(0, data.files.findIndex((file) => file.path === filePath))
|
|
@@ -368,6 +397,7 @@ export class GitDiffViewController {
|
|
|
368
397
|
}
|
|
369
398
|
|
|
370
399
|
async openCommitDiff({ hash, path = null, historyFilePath = null } = {}) {
|
|
400
|
+
this.isActive = true;
|
|
371
401
|
this.source = 'commit';
|
|
372
402
|
this.layoutMode = 'stacked';
|
|
373
403
|
this.commitHash = String(hash ?? '').trim() || null;
|
|
@@ -383,16 +413,10 @@ export class GitDiffViewController {
|
|
|
383
413
|
this.renderLoading('Loading commit summary...');
|
|
384
414
|
|
|
385
415
|
try {
|
|
386
|
-
const
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
const response = await fetch(resolveApiUrl(`/git/commit?${query.toString()}`));
|
|
391
|
-
const data = await response.json();
|
|
392
|
-
if (!response.ok) {
|
|
393
|
-
throw new Error(data.error || 'Failed to load git commit');
|
|
394
|
-
}
|
|
395
|
-
|
|
416
|
+
const data = await this.gitApiClient.readCommit({
|
|
417
|
+
hash: this.commitHash || '',
|
|
418
|
+
metaOnly: true,
|
|
419
|
+
});
|
|
396
420
|
this.data = data;
|
|
397
421
|
this.commitMeta = data.commit ?? null;
|
|
398
422
|
const initialIndex = path
|
|
@@ -476,6 +500,9 @@ export class GitDiffViewController {
|
|
|
476
500
|
}
|
|
477
501
|
|
|
478
502
|
renderLoading(message = 'Loading git diff...') {
|
|
503
|
+
if (!this.isActive) {
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
479
506
|
this.page?.classList.remove('hidden');
|
|
480
507
|
if (this.content) {
|
|
481
508
|
this.content.innerHTML = `<div class="diff-empty-state">${escapeHtml(message)}</div>`;
|
|
@@ -485,6 +512,9 @@ export class GitDiffViewController {
|
|
|
485
512
|
}
|
|
486
513
|
|
|
487
514
|
renderEmpty(message) {
|
|
515
|
+
if (!this.isActive) {
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
488
518
|
this.page?.classList.remove('hidden');
|
|
489
519
|
if (this.content) {
|
|
490
520
|
this.content.innerHTML = `<div class="diff-empty-state">${escapeHtml(message)}</div>`;
|
|
@@ -1053,37 +1083,21 @@ export class GitDiffViewController {
|
|
|
1053
1083
|
try {
|
|
1054
1084
|
let detail;
|
|
1055
1085
|
if (this.source === 'commit') {
|
|
1056
|
-
const
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
}
|
|
1062
|
-
|
|
1063
|
-
const response = await fetch(resolveApiUrl(`/git/commit?${query.toString()}`));
|
|
1064
|
-
const data = await response.json();
|
|
1065
|
-
if (!response.ok) {
|
|
1066
|
-
throw new Error(data.error || 'Failed to load commit file diff');
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1086
|
+
const data = await this.gitApiClient.readCommit({
|
|
1087
|
+
allowLargePatch: forceFullPatch,
|
|
1088
|
+
hash: this.commitHash || '',
|
|
1089
|
+
path: filePath,
|
|
1090
|
+
});
|
|
1069
1091
|
detail = {
|
|
1070
1092
|
...file,
|
|
1071
1093
|
...(data.files?.[0] ?? {}),
|
|
1072
1094
|
};
|
|
1073
1095
|
} else {
|
|
1074
|
-
const
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
}
|
|
1080
|
-
|
|
1081
|
-
const response = await fetch(resolveApiUrl(`/git/diff?${query.toString()}`));
|
|
1082
|
-
const data = await response.json();
|
|
1083
|
-
if (!response.ok) {
|
|
1084
|
-
throw new Error(data.error || 'Failed to load file diff');
|
|
1085
|
-
}
|
|
1086
|
-
|
|
1096
|
+
const data = await this.gitApiClient.readDiff({
|
|
1097
|
+
allowLargePatch: forceFullPatch,
|
|
1098
|
+
path: filePath,
|
|
1099
|
+
scope: this.requestScope,
|
|
1100
|
+
});
|
|
1087
1101
|
detail = {
|
|
1088
1102
|
...file,
|
|
1089
1103
|
...(data.files?.[0] ?? {}),
|
|
@@ -1187,6 +1201,9 @@ export class GitDiffViewController {
|
|
|
1187
1201
|
}
|
|
1188
1202
|
|
|
1189
1203
|
render() {
|
|
1204
|
+
if (!this.isActive) {
|
|
1205
|
+
return;
|
|
1206
|
+
}
|
|
1190
1207
|
this.page?.classList.remove('hidden');
|
|
1191
1208
|
|
|
1192
1209
|
const files = this.data?.files ?? [];
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { escapeHtml } from '../domain/vault-utils.js';
|
|
2
|
-
import { resolveApiUrl } from '../domain/runtime-paths.js';
|
|
3
2
|
import { buttonClassNames } from './components/ui/button.js';
|
|
4
3
|
import { segmentedButtonClassNames, segmentedControlClassNames } from './components/ui/segmented-control.js';
|
|
5
4
|
|
|
@@ -94,6 +93,7 @@ function renderHistoryRowTitle(commit = {}) {
|
|
|
94
93
|
export class GitPanelController {
|
|
95
94
|
constructor({
|
|
96
95
|
enabled = true,
|
|
96
|
+
gitApiClient = null,
|
|
97
97
|
onCommitStaged = () => {},
|
|
98
98
|
onOpenPullBackup = () => {},
|
|
99
99
|
onPullBranch = () => {},
|
|
@@ -109,6 +109,7 @@ export class GitPanelController {
|
|
|
109
109
|
toastController = null,
|
|
110
110
|
} = {}) {
|
|
111
111
|
this.enabled = enabled;
|
|
112
|
+
this.gitApiClient = gitApiClient;
|
|
112
113
|
this.onCommitStaged = onCommitStaged;
|
|
113
114
|
this.onOpenPullBackup = onOpenPullBackup;
|
|
114
115
|
this.onPullBranch = onPullBranch;
|
|
@@ -404,21 +405,12 @@ export class GitPanelController {
|
|
|
404
405
|
}
|
|
405
406
|
|
|
406
407
|
try {
|
|
407
|
-
const
|
|
408
|
-
const data = await response.json();
|
|
409
|
-
if (!response.ok) {
|
|
410
|
-
throw new Error(data.error || 'Failed to load git status');
|
|
411
|
-
}
|
|
412
|
-
|
|
408
|
+
const data = await this.gitApiClient.readStatus({ force });
|
|
413
409
|
this.status = data;
|
|
414
410
|
this.pullBackups = [];
|
|
415
411
|
if (data.isGitRepo) {
|
|
416
412
|
try {
|
|
417
|
-
const
|
|
418
|
-
const backupData = await backupResponse.json();
|
|
419
|
-
if (!backupResponse.ok) {
|
|
420
|
-
throw new Error(backupData.error || 'Failed to load pull backups');
|
|
421
|
-
}
|
|
413
|
+
const backupData = await this.gitApiClient.readPullBackups();
|
|
422
414
|
this.pullBackups = Array.isArray(backupData.backups) ? backupData.backups : [];
|
|
423
415
|
} catch (backupError) {
|
|
424
416
|
console.error('[git-panel] Failed to load pull backups:', backupError);
|
|
@@ -501,15 +493,10 @@ export class GitPanelController {
|
|
|
501
493
|
this.render();
|
|
502
494
|
|
|
503
495
|
try {
|
|
504
|
-
const
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
const data = await response.json();
|
|
509
|
-
if (!response.ok) {
|
|
510
|
-
throw new Error(data.error || 'Failed to load git history');
|
|
511
|
-
}
|
|
512
|
-
|
|
496
|
+
const data = await this.gitApiClient.readHistory({
|
|
497
|
+
limit: HISTORY_PAGE_SIZE,
|
|
498
|
+
offset: 0,
|
|
499
|
+
});
|
|
513
500
|
this.history = {
|
|
514
501
|
commits: Array.isArray(data.commits) ? data.commits : [],
|
|
515
502
|
error: '',
|
|
@@ -553,15 +540,10 @@ export class GitPanelController {
|
|
|
553
540
|
this.render();
|
|
554
541
|
|
|
555
542
|
try {
|
|
556
|
-
const
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
const data = await response.json();
|
|
561
|
-
if (!response.ok) {
|
|
562
|
-
throw new Error(data.error || 'Failed to load git history');
|
|
563
|
-
}
|
|
564
|
-
|
|
543
|
+
const data = await this.gitApiClient.readHistory({
|
|
544
|
+
limit: HISTORY_PAGE_SIZE,
|
|
545
|
+
offset: this.history.offset,
|
|
546
|
+
});
|
|
565
547
|
const nextCommits = Array.isArray(data.commits) ? data.commits : [];
|
|
566
548
|
this.history = {
|
|
567
549
|
commits: [...this.history.commits, ...nextCommits],
|
|
@@ -2,17 +2,24 @@ html[data-surface='export-document'] {
|
|
|
2
2
|
height: auto;
|
|
3
3
|
min-height: 100%;
|
|
4
4
|
overflow-x: hidden;
|
|
5
|
-
overflow-y:
|
|
5
|
+
overflow-y: hidden;
|
|
6
6
|
overscroll-behavior: auto;
|
|
7
|
+
scrollbar-width: none;
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
body[data-surface='export-document'] {
|
|
10
11
|
height: auto;
|
|
11
12
|
overflow-x: hidden;
|
|
12
|
-
overflow-y:
|
|
13
|
+
overflow-y: hidden;
|
|
13
14
|
overscroll-behavior: auto;
|
|
14
15
|
background: var(--color-bg);
|
|
15
16
|
color: var(--color-text);
|
|
17
|
+
scrollbar-width: none;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
html[data-surface='export-document']::-webkit-scrollbar,
|
|
21
|
+
body[data-surface='export-document']::-webkit-scrollbar {
|
|
22
|
+
display: none;
|
|
16
23
|
}
|
|
17
24
|
|
|
18
25
|
.export-page-shell {
|
|
@@ -78,10 +85,22 @@ body[data-surface='export-document'] {
|
|
|
78
85
|
overflow: visible;
|
|
79
86
|
}
|
|
80
87
|
|
|
88
|
+
.export-content .bases-table-shell,
|
|
89
|
+
.export-content pre {
|
|
90
|
+
overflow: visible;
|
|
91
|
+
}
|
|
92
|
+
|
|
81
93
|
.export-content table {
|
|
82
94
|
white-space: normal;
|
|
83
95
|
}
|
|
84
96
|
|
|
97
|
+
.export-content pre code {
|
|
98
|
+
width: auto;
|
|
99
|
+
white-space: pre-wrap;
|
|
100
|
+
word-break: break-word;
|
|
101
|
+
overflow-wrap: anywhere;
|
|
102
|
+
}
|
|
103
|
+
|
|
85
104
|
.export-diagram {
|
|
86
105
|
display: flex;
|
|
87
106
|
justify-content: center;
|
|
@@ -197,8 +216,18 @@ body[data-surface='export-document'] {
|
|
|
197
216
|
}
|
|
198
217
|
|
|
199
218
|
@media print {
|
|
219
|
+
html[data-surface='export-document'],
|
|
200
220
|
body[data-surface='export-document'] {
|
|
221
|
+
height: auto;
|
|
222
|
+
overflow: hidden !important;
|
|
201
223
|
background: var(--color-surface);
|
|
224
|
+
scrollbar-width: none;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
html[data-surface='export-document']::-webkit-scrollbar,
|
|
228
|
+
body[data-surface='export-document']::-webkit-scrollbar,
|
|
229
|
+
.export-content *::-webkit-scrollbar {
|
|
230
|
+
display: none;
|
|
202
231
|
}
|
|
203
232
|
|
|
204
233
|
.export-page-shell {
|
|
@@ -218,6 +247,20 @@ body[data-surface='export-document'] {
|
|
|
218
247
|
border: 0;
|
|
219
248
|
border-radius: 0;
|
|
220
249
|
box-shadow: none;
|
|
250
|
+
overflow: visible;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.export-content pre,
|
|
254
|
+
.export-content .table-wrapper,
|
|
255
|
+
.export-content .bases-table-shell {
|
|
256
|
+
overflow: visible !important;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.export-content pre code {
|
|
260
|
+
width: auto;
|
|
261
|
+
white-space: pre-wrap;
|
|
262
|
+
word-break: break-word;
|
|
263
|
+
overflow-wrap: anywhere;
|
|
221
264
|
}
|
|
222
265
|
|
|
223
266
|
.export-content h1,
|