collabmd 0.1.33 → 0.1.34
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/{index-Czg_KL-i.js → index-BLrtj9YM.js} +2 -2
- package/dist/client/assets/{main-DeowJOSp.js → main-CfSHaGes.js} +86 -86
- package/dist/client/index.html +1 -1
- package/package.json +2 -1
- package/src/client/application/app-shell/git-feature.js +44 -36
- package/src/client/application/app-shell/ui-feature-shell.js +84 -63
- package/src/client/presentation/excalidraw-embed-controller.js +4 -1
- package/src/client/presentation/file-history-view-controller.js +9 -1
- package/src/client/presentation/git-panel-controller.js +101 -91
- package/src/server/domain/backlink-index.js +41 -22
- package/src/server/infrastructure/http/create-request-handler.js +63 -28
- package/src/server/infrastructure/http/create-vault-api-command-handler.js +275 -256
- package/src/server/infrastructure/http/create-vault-api-query-handler.js +255 -233
- package/src/server/infrastructure/persistence/vault-file-store.js +68 -12
package/dist/client/index.html
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
document.documentElement.setAttribute('data-initial-file-requested', 'true');
|
|
16
16
|
}
|
|
17
17
|
</script>
|
|
18
|
-
<script type="module" crossorigin src="./assets/index-
|
|
18
|
+
<script type="module" crossorigin src="./assets/index-BLrtj9YM.js"></script>
|
|
19
19
|
<link rel="modulepreload" crossorigin href="./assets/runtime-config-loader-_D2KZKn-.js">
|
|
20
20
|
<link rel="modulepreload" crossorigin href="./assets/preload-helper-Bo9GmnuQ.js">
|
|
21
21
|
<link rel="modulepreload" crossorigin href="./assets/base-h1uscjTi.js">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "collabmd",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.34",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Collaborative markdown vault — like Obsidian, but online. Serve any directory of markdown files for realtime collaborative editing.",
|
|
6
6
|
"repository": {
|
|
@@ -84,6 +84,7 @@
|
|
|
84
84
|
"openid-client": "^6.8.2",
|
|
85
85
|
"react": "^19.2.4",
|
|
86
86
|
"react-dom": "^19.2.4",
|
|
87
|
+
"sharp": "^0.34.5",
|
|
87
88
|
"ws": "^8.20.0",
|
|
88
89
|
"y-codemirror.next": "^0.3.5",
|
|
89
90
|
"y-protocols": "^1.0.7",
|
|
@@ -232,6 +232,48 @@ export const gitFeature = {
|
|
|
232
232
|
await this.fileHistoryView.openFileHistory({ filePath });
|
|
233
233
|
},
|
|
234
234
|
|
|
235
|
+
async _loadGitFileSnapshot({ hash, filePath, resolvedCurrentFilePath }) {
|
|
236
|
+
const data = await this.gitApiClient.readFileSnapshot({
|
|
237
|
+
hash,
|
|
238
|
+
path: filePath,
|
|
239
|
+
});
|
|
240
|
+
this.setStaticPreviewDocument?.({
|
|
241
|
+
...data,
|
|
242
|
+
currentFilePath: resolvedCurrentFilePath,
|
|
243
|
+
});
|
|
244
|
+
this.resetPreviewMode();
|
|
245
|
+
this.elements.markdownToolbar?.classList.add('hidden');
|
|
246
|
+
this.elements.outlineToggle?.classList.toggle('hidden', data.fileKind !== 'markdown');
|
|
247
|
+
|
|
248
|
+
if (data.fileKind === 'markdown' || data.fileKind === 'mermaid' || data.fileKind === 'plantuml') {
|
|
249
|
+
if (data.fileKind === 'mermaid') {
|
|
250
|
+
this.elements.previewContent?.classList.add('is-mermaid-file-preview');
|
|
251
|
+
} else if (data.fileKind === 'plantuml') {
|
|
252
|
+
this.elements.previewContent?.classList.add('is-plantuml-file-preview');
|
|
253
|
+
}
|
|
254
|
+
this.previewRenderer.beginDocumentLoad();
|
|
255
|
+
this.previewRenderer.queueRender();
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
this.elements.outlineToggle?.classList.add('hidden');
|
|
260
|
+
this.renderTextFilePreview?.({
|
|
261
|
+
content: data.content,
|
|
262
|
+
filePath: resolvedCurrentFilePath,
|
|
263
|
+
});
|
|
264
|
+
},
|
|
265
|
+
|
|
266
|
+
_handleGitFilePreviewError(error, resolvedCurrentFilePath) {
|
|
267
|
+
console.error('[git-preview] Failed to load file snapshot:', error);
|
|
268
|
+
this.clearStaticPreviewDocument?.();
|
|
269
|
+
this.toastController.show('Failed to load historical file preview');
|
|
270
|
+
this.renderTextFilePreview?.({
|
|
271
|
+
content: 'Failed to load historical file preview.',
|
|
272
|
+
filePath: resolvedCurrentFilePath,
|
|
273
|
+
});
|
|
274
|
+
this.elements.outlineToggle?.classList.add('hidden');
|
|
275
|
+
},
|
|
276
|
+
|
|
235
277
|
async showGitFilePreview({ hash, filePath = null, currentFilePath = null } = {}) {
|
|
236
278
|
const resolvedCurrentFilePath = String(currentFilePath ?? '').trim() || filePath;
|
|
237
279
|
if (!hash || !filePath || !resolvedCurrentFilePath) {
|
|
@@ -256,43 +298,9 @@ export const gitFeature = {
|
|
|
256
298
|
this.syncFileHistoryButton({ filePath: resolvedCurrentFilePath, mode: 'history-preview' });
|
|
257
299
|
|
|
258
300
|
try {
|
|
259
|
-
|
|
260
|
-
hash,
|
|
261
|
-
path: filePath,
|
|
262
|
-
});
|
|
263
|
-
this.setStaticPreviewDocument?.({
|
|
264
|
-
...data,
|
|
265
|
-
currentFilePath: resolvedCurrentFilePath,
|
|
266
|
-
});
|
|
267
|
-
this.resetPreviewMode();
|
|
268
|
-
this.elements.markdownToolbar?.classList.add('hidden');
|
|
269
|
-
this.elements.outlineToggle?.classList.toggle('hidden', data.fileKind !== 'markdown');
|
|
270
|
-
|
|
271
|
-
if (data.fileKind === 'markdown' || data.fileKind === 'mermaid' || data.fileKind === 'plantuml') {
|
|
272
|
-
if (data.fileKind === 'mermaid') {
|
|
273
|
-
this.elements.previewContent?.classList.add('is-mermaid-file-preview');
|
|
274
|
-
} else if (data.fileKind === 'plantuml') {
|
|
275
|
-
this.elements.previewContent?.classList.add('is-plantuml-file-preview');
|
|
276
|
-
}
|
|
277
|
-
this.previewRenderer.beginDocumentLoad();
|
|
278
|
-
this.previewRenderer.queueRender();
|
|
279
|
-
return;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
this.elements.outlineToggle?.classList.add('hidden');
|
|
283
|
-
this.renderTextFilePreview?.({
|
|
284
|
-
content: data.content,
|
|
285
|
-
filePath: resolvedCurrentFilePath,
|
|
286
|
-
});
|
|
301
|
+
await this._loadGitFileSnapshot({ hash, filePath, resolvedCurrentFilePath });
|
|
287
302
|
} catch (error) {
|
|
288
|
-
|
|
289
|
-
this.clearStaticPreviewDocument?.();
|
|
290
|
-
this.toastController.show('Failed to load historical file preview');
|
|
291
|
-
this.renderTextFilePreview?.({
|
|
292
|
-
content: 'Failed to load historical file preview.',
|
|
293
|
-
filePath: resolvedCurrentFilePath,
|
|
294
|
-
});
|
|
295
|
-
this.elements.outlineToggle?.classList.add('hidden');
|
|
303
|
+
this._handleGitFilePreviewError(error, resolvedCurrentFilePath);
|
|
296
304
|
}
|
|
297
305
|
},
|
|
298
306
|
|
|
@@ -136,31 +136,7 @@ function promptForVersionReload(payload = null) {
|
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
/** @this {UiShellContext} */
|
|
139
|
-
function
|
|
140
|
-
this.elements.emptyStateNewFileBtn?.addEventListener('click', () => {
|
|
141
|
-
this.fileExplorer.actionController.openRootCreateMenu({
|
|
142
|
-
anchor: this.elements.emptyStateNewFileBtn,
|
|
143
|
-
});
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
this.elements.emptyStateSearchBtn?.addEventListener('click', () => {
|
|
147
|
-
void this.toggleQuickSwitcher();
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
this.elements.chatToggleButton?.addEventListener('click', () => {
|
|
151
|
-
this.toggleChatPanel();
|
|
152
|
-
this.closeToolbarOverflowMenu?.();
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
this.elements.chatForm?.addEventListener('submit', (event) => {
|
|
156
|
-
event.preventDefault();
|
|
157
|
-
this.handleChatSubmit();
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
this.elements.chatNotificationButton?.addEventListener('click', () => {
|
|
161
|
-
void this.handleChatNotificationToggle();
|
|
162
|
-
});
|
|
163
|
-
|
|
139
|
+
function bindToolbarEvents() {
|
|
164
140
|
this.elements.shareButton?.addEventListener('click', () => {
|
|
165
141
|
void this.copyCurrentLink();
|
|
166
142
|
this.closeToolbarOverflowMenu?.();
|
|
@@ -197,7 +173,10 @@ function bindEvents() {
|
|
|
197
173
|
this.openDisplayNameDialog();
|
|
198
174
|
this.closeToolbarOverflowMenu?.();
|
|
199
175
|
});
|
|
176
|
+
}
|
|
200
177
|
|
|
178
|
+
/** @this {UiShellContext} */
|
|
179
|
+
function bindDialogEvents() {
|
|
201
180
|
this.elements.displayNameCancel?.addEventListener('click', () => {
|
|
202
181
|
this.elements.displayNameDialog?.close();
|
|
203
182
|
});
|
|
@@ -233,14 +212,6 @@ function bindEvents() {
|
|
|
233
212
|
}
|
|
234
213
|
});
|
|
235
214
|
|
|
236
|
-
this.elements.markdownToolbar?.addEventListener('click', (event) => {
|
|
237
|
-
this.handleMarkdownToolbarClick?.(event);
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
this.elements.markdownToolbar?.addEventListener('keydown', (event) => {
|
|
241
|
-
this.handleMarkdownToolbarKeydown?.(event);
|
|
242
|
-
});
|
|
243
|
-
|
|
244
215
|
this.elements.displayNameForm?.addEventListener('submit', (event) => {
|
|
245
216
|
event.preventDefault();
|
|
246
217
|
this.handleDisplayNameSubmit();
|
|
@@ -250,6 +221,44 @@ function bindEvents() {
|
|
|
250
221
|
event.preventDefault();
|
|
251
222
|
void this.handleGitCommitSubmit();
|
|
252
223
|
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** @this {UiShellContext} */
|
|
227
|
+
function bindEvents() {
|
|
228
|
+
this.elements.emptyStateNewFileBtn?.addEventListener('click', () => {
|
|
229
|
+
this.fileExplorer.actionController.openRootCreateMenu({
|
|
230
|
+
anchor: this.elements.emptyStateNewFileBtn,
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
this.elements.emptyStateSearchBtn?.addEventListener('click', () => {
|
|
235
|
+
void this.toggleQuickSwitcher();
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
this.elements.chatToggleButton?.addEventListener('click', () => {
|
|
239
|
+
this.toggleChatPanel();
|
|
240
|
+
this.closeToolbarOverflowMenu?.();
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
this.elements.chatForm?.addEventListener('submit', (event) => {
|
|
244
|
+
event.preventDefault();
|
|
245
|
+
this.handleChatSubmit();
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
this.elements.chatNotificationButton?.addEventListener('click', () => {
|
|
249
|
+
void this.handleChatNotificationToggle();
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
bindToolbarEvents.call(this);
|
|
253
|
+
bindDialogEvents.call(this);
|
|
254
|
+
|
|
255
|
+
this.elements.markdownToolbar?.addEventListener('click', (event) => {
|
|
256
|
+
this.handleMarkdownToolbarClick?.(event);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
this.elements.markdownToolbar?.addEventListener('keydown', (event) => {
|
|
260
|
+
this.handleMarkdownToolbarKeydown?.(event);
|
|
261
|
+
});
|
|
253
262
|
|
|
254
263
|
this.elements.tabLockTakeoverButton?.addEventListener('click', () => {
|
|
255
264
|
this.handleTabTakeover();
|
|
@@ -299,43 +308,53 @@ function bindEvents() {
|
|
|
299
308
|
});
|
|
300
309
|
|
|
301
310
|
document.addEventListener('pointerdown', (event) => {
|
|
302
|
-
this.
|
|
311
|
+
this.handleDocumentPointerDown(event);
|
|
312
|
+
});
|
|
303
313
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
) {
|
|
309
|
-
this.closeToolbarOverflowMenu();
|
|
310
|
-
}
|
|
314
|
+
document.addEventListener('keydown', (event) => {
|
|
315
|
+
this.handleDocumentKeydown(event);
|
|
316
|
+
});
|
|
317
|
+
}
|
|
311
318
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
319
|
+
/** @this {UiShellContext} */
|
|
320
|
+
function handleDocumentPointerDown(event) {
|
|
321
|
+
this.handleMarkdownToolbarDocumentPointerDown?.(event);
|
|
322
|
+
|
|
323
|
+
if (
|
|
324
|
+
this.toolbarOverflowOpen
|
|
325
|
+
&& !this.elements.toolbarOverflowMenu?.contains(event.target)
|
|
326
|
+
&& !this.elements.toolbarOverflowToggle?.contains(event.target)
|
|
327
|
+
) {
|
|
328
|
+
this.closeToolbarOverflowMenu();
|
|
329
|
+
}
|
|
315
330
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
331
|
+
if (!this.chatIsOpen) {
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
319
334
|
|
|
320
|
-
|
|
321
|
-
|
|
335
|
+
if (this.elements.chatContainer?.contains(event.target)) {
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
322
338
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
this.closeToolbarOverflowMenu();
|
|
326
|
-
return;
|
|
327
|
-
}
|
|
339
|
+
this.closeChatPanel();
|
|
340
|
+
}
|
|
328
341
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
342
|
+
/** @this {UiShellContext} */
|
|
343
|
+
function handleDocumentKeydown(event) {
|
|
344
|
+
if (event.key === 'Escape' && this.toolbarOverflowOpen) {
|
|
345
|
+
this.closeToolbarOverflowMenu();
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
333
348
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
349
|
+
if (event.key === 'Escape' && this.chatIsOpen) {
|
|
350
|
+
this.closeChatPanel();
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
if ((event.metaKey || event.ctrlKey) && event.key === 'k') {
|
|
355
|
+
event.preventDefault();
|
|
356
|
+
void this.toggleQuickSwitcher();
|
|
357
|
+
}
|
|
339
358
|
}
|
|
340
359
|
|
|
341
360
|
function isNestedTaskListClickTarget(target, taskItem) {
|
|
@@ -521,6 +540,8 @@ export const uiFeatureShellMethods = {
|
|
|
521
540
|
closeToolbarOverflowMenu,
|
|
522
541
|
getStoredLineWrapping,
|
|
523
542
|
handleConnectionChange,
|
|
543
|
+
handleDocumentKeydown,
|
|
544
|
+
handleDocumentPointerDown,
|
|
524
545
|
handlePreviewContentClick,
|
|
525
546
|
handleThemeChange,
|
|
526
547
|
hideEditorLoading,
|
|
@@ -153,6 +153,7 @@ export class ExcalidrawEmbedController {
|
|
|
153
153
|
this.hydrationIdleId = null;
|
|
154
154
|
this.hydrationQueue = [];
|
|
155
155
|
this.hydrationInProgress = false;
|
|
156
|
+
this._exitMaximizedEmbed();
|
|
156
157
|
if (this.overlayRoot) {
|
|
157
158
|
this.overlayRoot.hidden = true;
|
|
158
159
|
}
|
|
@@ -762,7 +763,9 @@ export class ExcalidrawEmbedController {
|
|
|
762
763
|
enterMaximize();
|
|
763
764
|
}
|
|
764
765
|
});
|
|
765
|
-
openBtn.addEventListener('click', () => {
|
|
766
|
+
openBtn.addEventListener('click', (event) => {
|
|
767
|
+
event.preventDefault();
|
|
768
|
+
this._exitMaximizedEmbed();
|
|
766
769
|
this.onOpenFile?.(entry.filePath);
|
|
767
770
|
});
|
|
768
771
|
|
|
@@ -516,9 +516,15 @@ export class FileHistoryViewController {
|
|
|
516
516
|
additions: Number(selectedEntry.additions || 0),
|
|
517
517
|
deletions: Number(selectedEntry.deletions || 0),
|
|
518
518
|
} : null);
|
|
519
|
+
const hasSelection = Boolean(selectedEntry);
|
|
520
|
+
|
|
521
|
+
this.syncToolbarIndicators(selectedEntry, selectedSummary, hasSelection);
|
|
522
|
+
this.syncToolbarButtonStates(hasSelection);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
syncToolbarIndicators(selectedEntry, selectedSummary, hasSelection) {
|
|
519
526
|
const additions = Number(selectedSummary?.additions || 0);
|
|
520
527
|
const deletions = Number(selectedSummary?.deletions || 0);
|
|
521
|
-
const hasSelection = Boolean(selectedEntry);
|
|
522
528
|
|
|
523
529
|
if (this.fileIndicator) {
|
|
524
530
|
this.fileIndicator.textContent = selectedEntry?.type === 'commit'
|
|
@@ -535,7 +541,9 @@ export class FileHistoryViewController {
|
|
|
535
541
|
`;
|
|
536
542
|
this.stats.classList.toggle('hidden', !hasSelection);
|
|
537
543
|
}
|
|
544
|
+
}
|
|
538
545
|
|
|
546
|
+
syncToolbarButtonStates(hasSelection) {
|
|
539
547
|
this.backToHistoryButton?.classList.add('hidden');
|
|
540
548
|
this.gitActionsGroup?.classList.add('hidden');
|
|
541
549
|
this.layoutToggle?.classList.add('hidden');
|
|
@@ -149,115 +149,125 @@ export class GitPanelController {
|
|
|
149
149
|
};
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
void this.setMode(nextMode);
|
|
161
|
-
}
|
|
162
|
-
return;
|
|
152
|
+
_handlePanelModeClick(event) {
|
|
153
|
+
const modeButton = event.target instanceof Element
|
|
154
|
+
? event.target.closest('[data-git-panel-mode]')
|
|
155
|
+
: null;
|
|
156
|
+
if (modeButton) {
|
|
157
|
+
const nextMode = modeButton.getAttribute('data-git-panel-mode');
|
|
158
|
+
if (nextMode === 'changes' || nextMode === 'history') {
|
|
159
|
+
void this.setMode(nextMode);
|
|
163
160
|
}
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
164
165
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
166
|
+
_handleSectionToggleClick(event) {
|
|
167
|
+
const toggleButton = event.target instanceof Element
|
|
168
|
+
? event.target.closest('[data-git-section-toggle]')
|
|
169
|
+
: null;
|
|
170
|
+
if (toggleButton) {
|
|
171
|
+
this.toggleSection(toggleButton.getAttribute('data-git-section-toggle'));
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
173
176
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
177
|
+
_handleCommitHistoryClick(event) {
|
|
178
|
+
const historyButton = event.target instanceof Element
|
|
179
|
+
? event.target.closest('[data-git-commit-hash]')
|
|
180
|
+
: null;
|
|
181
|
+
if (historyButton && !event.target.closest('[data-git-history-load-more]')) {
|
|
182
|
+
const hash = historyButton.getAttribute('data-git-commit-hash');
|
|
183
|
+
if (hash) {
|
|
182
184
|
this.onSelectCommit(hash, { path: this.selection.commitHash === hash ? this.selection.path : null });
|
|
183
|
-
return;
|
|
184
185
|
}
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
185
190
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
191
|
+
_handleFileSelectionClick(event) {
|
|
192
|
+
const fileButton = event.target instanceof Element
|
|
193
|
+
? event.target.closest('[data-git-path]')
|
|
194
|
+
: null;
|
|
195
|
+
if (fileButton && !event.target.closest('[data-git-file-action]')) {
|
|
196
|
+
const filePath = fileButton.getAttribute('data-git-path');
|
|
197
|
+
if (filePath) {
|
|
198
|
+
this.onSelectDiff(filePath, { scope: fileButton.getAttribute('data-git-scope') || 'working-tree' });
|
|
192
199
|
}
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
193
204
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
+
_handleFileActionClick(event) {
|
|
206
|
+
const actionButton = event.target instanceof Element
|
|
207
|
+
? event.target.closest('[data-git-file-action]')
|
|
208
|
+
: null;
|
|
209
|
+
if (actionButton) {
|
|
210
|
+
const action = actionButton.getAttribute('data-git-file-action');
|
|
211
|
+
const filePath = actionButton.getAttribute('data-git-path');
|
|
212
|
+
if (action && filePath) {
|
|
213
|
+
event.preventDefault();
|
|
214
|
+
event.stopPropagation();
|
|
215
|
+
void this.handleFileAction(action, filePath, actionButton.getAttribute('data-git-scope') || 'working-tree');
|
|
205
216
|
}
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
206
221
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
222
|
+
_handlePanelClick(event) {
|
|
223
|
+
if (this._handlePanelModeClick(event)) return;
|
|
224
|
+
if (this._handleSectionToggleClick(event)) return;
|
|
225
|
+
if (this._handleCommitHistoryClick(event)) return;
|
|
226
|
+
|
|
227
|
+
if (event.target instanceof Element && event.target.closest('[data-git-history-load-more]')) {
|
|
228
|
+
void this.loadMoreHistory();
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (this._handleFileSelectionClick(event)) return;
|
|
233
|
+
|
|
234
|
+
const pullBackupButton = event.target instanceof Element
|
|
235
|
+
? event.target.closest('[data-git-pull-backup-path]')
|
|
236
|
+
: null;
|
|
237
|
+
if (pullBackupButton) {
|
|
238
|
+
const summaryPath = pullBackupButton.getAttribute('data-git-pull-backup-path');
|
|
239
|
+
if (summaryPath) {
|
|
215
240
|
this.onOpenPullBackup(summaryPath);
|
|
216
|
-
return;
|
|
217
241
|
}
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
218
244
|
|
|
219
|
-
|
|
220
|
-
? event.target.closest('[data-git-file-action]')
|
|
221
|
-
: null;
|
|
222
|
-
if (actionButton) {
|
|
223
|
-
const action = actionButton.getAttribute('data-git-file-action');
|
|
224
|
-
const filePath = actionButton.getAttribute('data-git-path');
|
|
225
|
-
const scope = actionButton.getAttribute('data-git-scope') || 'working-tree';
|
|
226
|
-
if (!action || !filePath) {
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
245
|
+
if (this._handleFileActionClick(event)) return;
|
|
229
246
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
}
|
|
247
|
+
if (event.target instanceof Element && event.target.closest('[data-git-view-all]')) {
|
|
248
|
+
this.onViewAllDiff();
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
235
251
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
this.onViewAllDiff();
|
|
241
|
-
return;
|
|
242
|
-
}
|
|
252
|
+
if (event.target instanceof Element && event.target.closest('[data-git-commit-staged]')) {
|
|
253
|
+
void this.handleCommitStaged();
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
243
256
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
257
|
+
const syncButton = event.target instanceof Element
|
|
258
|
+
? event.target.closest('[data-git-sync-action]')
|
|
259
|
+
: null;
|
|
260
|
+
if (syncButton) {
|
|
261
|
+
const action = syncButton.getAttribute('data-git-sync-action');
|
|
262
|
+
if (action === 'pull' || action === 'push') {
|
|
263
|
+
void this.handleSyncAction(action);
|
|
250
264
|
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
251
267
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
if (syncButton) {
|
|
256
|
-
const action = syncButton.getAttribute('data-git-sync-action');
|
|
257
|
-
if (action === 'pull' || action === 'push') {
|
|
258
|
-
void this.handleSyncAction(action);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
268
|
+
initialize() {
|
|
269
|
+
this.panel?.addEventListener('click', (event) => {
|
|
270
|
+
this._handlePanelClick(event);
|
|
261
271
|
});
|
|
262
272
|
|
|
263
273
|
this.searchInput?.addEventListener('input', (event) => {
|