clay-server 5.3.0-beta.5 → 5.3.0-beta.6
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/lib/clay-product-control-tools.js +2 -2
- package/lib/clay-product-control.js +1 -1
- package/lib/clay-screen-controls.js +1 -0
- package/lib/clay-split-view-awareness.js +5 -2
- package/lib/clay-split-view-controls.js +14 -7
- package/lib/clay-split-view-input.js +5 -4
- package/lib/clay-split-view-render-proof.js +14 -4
- package/lib/clay-view-workspace-input.js +71 -0
- package/lib/project-file-history.js +11 -9
- package/lib/project-file-watch.js +26 -7
- package/lib/project-filesystem.js +5 -4
- package/lib/project-shared-browser.js +7 -3
- package/lib/project-split-view-document.js +16 -2
- package/lib/project-split-views.js +15 -294
- package/lib/project-user-message.js +4 -3
- package/lib/project-vendor-login.js +2 -2
- package/lib/project-view-input.js +11 -0
- package/lib/project-view-pair.js +26 -0
- package/lib/project-view-store.js +346 -0
- package/lib/project-view-terminal-binding.js +16 -0
- package/lib/project-view-workspace.js +126 -0
- package/lib/project.js +1 -0
- package/lib/public/app.js +2 -0
- package/lib/public/css/issues.css +3 -0
- package/lib/public/css/pane.css +5 -1
- package/lib/public/css/right-workbench.css +0 -1
- package/lib/public/css/scheduled-tasks.css +7 -0
- package/lib/public/css/split-view-layout.css +37 -3
- package/lib/public/css/tool-pane.css +127 -0
- package/lib/public/index.html +1 -1
- package/lib/public/modules/clay-file-links.js +2 -1
- package/lib/public/modules/clay-split-view-screen.js +6 -3
- package/lib/public/modules/clay-tool-pane-screen.js +35 -0
- package/lib/public/modules/file-history-snapshot.js +12 -0
- package/lib/public/modules/file-pane-entrypoints.js +55 -0
- package/lib/public/modules/file-pane-history.js +78 -0
- package/lib/public/modules/file-pane-instances.js +140 -0
- package/lib/public/modules/file-pane-links.js +41 -0
- package/lib/public/modules/file-pane-render.js +48 -0
- package/lib/public/modules/file-pane-review.js +26 -0
- package/lib/public/modules/file-pane-toolbar.js +54 -0
- package/lib/public/modules/file-viewer-source.js +70 -0
- package/lib/public/modules/filebrowser.js +43 -82
- package/lib/public/modules/git-panel.js +5 -0
- package/lib/public/modules/issues.js +3 -4
- package/lib/public/modules/linear-panel.js +2 -2
- package/lib/public/modules/mate-knowledge-workbench.js +10 -6
- package/lib/public/modules/notifications.js +4 -1
- package/lib/public/modules/pane-activation.js +2 -0
- package/lib/public/modules/pane-binding.js +5 -1
- package/lib/public/modules/pane-browser-bridge.js +6 -2
- package/lib/public/modules/pane-browser-transport.js +110 -0
- package/lib/public/modules/plantuml-preview.js +12 -12
- package/lib/public/modules/right-workbench.js +34 -15
- package/lib/public/modules/scheduled-tasks.js +7 -6
- package/lib/public/modules/shared-browser.js +69 -9
- package/lib/public/modules/split-pane-renderer.js +1 -0
- package/lib/public/modules/split-view-drag-preview.js +90 -0
- package/lib/public/modules/split-view-layout-client.js +1 -1
- package/lib/public/modules/split-view-presentation-drag.js +36 -13
- package/lib/public/modules/split-view-presentation-drop.js +21 -18
- package/lib/public/modules/split-view-presentation-renderer.js +15 -10
- package/lib/public/modules/split-view-presentations.js +25 -33
- package/lib/public/modules/split-view.js +9 -2
- package/lib/public/modules/sticky-notes-browser.js +2 -2
- package/lib/public/modules/terminal.js +46 -19
- package/lib/public/modules/theme.js +1 -6
- package/lib/public/modules/tool-pane-chrome.js +82 -0
- package/lib/public/modules/tool-pane-drag.js +134 -0
- package/lib/public/modules/tool-pane-layout.js +95 -0
- package/lib/public/modules/tool-pane-legacy.js +60 -0
- package/lib/public/modules/tool-pane-tree.js +51 -0
- package/lib/public/modules/view-legacy-coordinates.js +16 -0
- package/lib/public/modules/view-mutations.js +24 -0
- package/lib/public/modules/view-pair-presentation.js +74 -0
- package/lib/public/modules/view-pair-validation.js +12 -0
- package/lib/public/modules/view-presentation-state.js +37 -0
- package/lib/public/modules/view-workspace-controller.js +210 -0
- package/lib/public/modules/view-workspace-state.js +103 -0
- package/lib/public/modules/view-workspace-validation.js +47 -0
- package/lib/public/modules/wireframe-workbench.js +11 -0
- package/lib/public/modules/workbench-layout-preference.js +12 -5
- package/lib/public/modules/workbench-panels.js +21 -0
- package/lib/public/pane-assets/{app-6H5S2Y3Z.js → app-7UZ727NA.js} +1 -1
- package/lib/public/pane-assets/chunk-2AIWCI6Y.js +1 -0
- package/lib/public/pane-assets/chunk-6MIHIQ2W.js +1 -0
- package/lib/public/pane-assets/chunk-6NYCNWVF.js +1 -0
- package/lib/public/pane-assets/chunk-6QFLYOVY.js +1 -0
- package/lib/public/pane-assets/chunk-6UJ2ALOB.js +1 -0
- package/lib/public/pane-assets/chunk-6XK2OATZ.js +1 -0
- package/lib/public/pane-assets/chunk-BKIDR2ME.js +1 -0
- package/lib/public/pane-assets/chunk-BMHTBRMO.js +1 -0
- package/lib/public/pane-assets/chunk-GEFCFZEN.js +1 -0
- package/lib/public/pane-assets/chunk-GN2NQEVC.js +2 -0
- package/lib/public/pane-assets/chunk-IMLMBPT4.js +166 -0
- package/lib/public/pane-assets/chunk-JIV7O5GN.js +1 -0
- package/lib/public/pane-assets/chunk-K5S6AILM.js +1 -0
- package/lib/public/pane-assets/chunk-LDIZLKB2.js +1 -0
- package/lib/public/pane-assets/chunk-OWNNLZ36.js +1 -0
- package/lib/public/pane-assets/chunk-P2C3LOWL.js +3 -0
- package/lib/public/pane-assets/chunk-PV4PCH2V.js +2 -0
- package/lib/public/pane-assets/chunk-R4LMPTKU.js +1 -0
- package/lib/public/pane-assets/chunk-R7QVVFUG.js +1 -0
- package/lib/public/pane-assets/chunk-TMGSDFJI.js +1 -0
- package/lib/public/pane-assets/chunk-VKYBAVWT.js +1 -0
- package/lib/public/pane-assets/chunk-VNAV23CM.js +1 -0
- package/lib/public/pane-assets/chunk-VWTHIQCE.js +1 -0
- package/lib/public/pane-assets/chunk-VZ2OKDAO.js +1 -0
- package/lib/public/pane-assets/chunk-WM3K5AFH.js +1 -0
- package/lib/public/pane-assets/chunk-XOB3O327.js +1 -0
- package/lib/public/pane-assets/chunk-XOOUCFYT.js +1 -0
- package/lib/public/pane-assets/manifest.json +426 -381
- package/lib/public/pane-assets/style-ZM7OOU3M.css +1 -0
- package/lib/public/style.css +1 -0
- package/lib/server-workbench-layout-settings.js +3 -3
- package/lib/split-view-layout.js +11 -7
- package/lib/users-workbench-layout-preferences.js +14 -4
- package/lib/workbench-window-layout.js +30 -0
- package/package.json +1 -1
- package/lib/public/pane-assets/chunk-3QV5SDC4.js +0 -1
- package/lib/public/pane-assets/chunk-4FM3U3DW.js +0 -1
- package/lib/public/pane-assets/chunk-7GZH3FZY.js +0 -1
- package/lib/public/pane-assets/chunk-AGJTF5WQ.js +0 -1
- package/lib/public/pane-assets/chunk-DGOFGEUK.js +0 -1
- package/lib/public/pane-assets/chunk-I57URYSL.js +0 -1
- package/lib/public/pane-assets/chunk-NPKRTUNG.js +0 -2
- package/lib/public/pane-assets/chunk-VGA2Y3D2.js +0 -2
- package/lib/public/pane-assets/chunk-WKO3T75E.js +0 -167
- package/lib/public/pane-assets/style-TSRDU54Z.css +0 -1
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { filePaneState, updateFilePaneState, repaintFilePane } from './file-pane-instances.js';
|
|
2
|
+
import { renderSplitDiff, renderUnifiedDiff } from './diff.js';
|
|
3
|
+
import { renderCodeWithLineNumbers, mapExtToLanguage } from './file-viewer-source.js';
|
|
4
|
+
|
|
5
|
+
var callbacks = new Map();
|
|
6
|
+
export function bindFileReview(state, review) {
|
|
7
|
+
if (review) callbacks.set(state.instanceId, { requestId: state.requestId, context: state.context, review: review });
|
|
8
|
+
else callbacks.delete(state.instanceId);
|
|
9
|
+
}
|
|
10
|
+
export function releaseFileReview(id) { callbacks.delete(id); }
|
|
11
|
+
export function paintFileReview(body, state) {
|
|
12
|
+
var bar = document.createElement('div'); bar.className = 'file-history-view-bar';
|
|
13
|
+
var receipt = callbacks.get(state.instanceId);
|
|
14
|
+
function current() { var live = filePaneState(state.instanceId); return live && live.requestId === state.requestId && live.context === state.context; }
|
|
15
|
+
function button(label, callback) { var b = document.createElement('button'); b.type = 'button'; b.textContent = label; b.disabled = !callback; b.addEventListener('click', function () { if (current() && callback) callback(); }); bar.appendChild(b); }
|
|
16
|
+
button('Back to file', function () { updateFilePaneState(state.instanceId, { diff: null }); repaintFilePane(state.instanceId); });
|
|
17
|
+
['Split', 'Unified', 'Source'].forEach(function (mode) { button(mode, function () { updateFilePaneState(state.instanceId, { reviewMode: mode.toLowerCase() }); repaintFilePane(state.instanceId); }); });
|
|
18
|
+
if (receipt && receipt.requestId === state.requestId && receipt.context === state.context) {
|
|
19
|
+
var review = receipt.review, label = document.createElement('span'); label.textContent = (review.index + 1) + ' of ' + review.total; bar.appendChild(label);
|
|
20
|
+
button('Previous file', review.previous); button('Next file', review.next); if (review.askAgent) button('Ask agent', review.askAgent);
|
|
21
|
+
}
|
|
22
|
+
body.appendChild(bar);
|
|
23
|
+
var content = document.createElement('div'), ext = state.resource.path.split('.').pop(); body.appendChild(content);
|
|
24
|
+
if (state.reviewMode === 'source') renderCodeWithLineNumbers(content, state.diff.newStr || '', ext);
|
|
25
|
+
else content.appendChild((state.reviewMode === 'unified' ? renderUnifiedDiff : renderSplitDiff)(state.diff.oldStr || '', state.diff.newStr || '', mapExtToLanguage(ext)));
|
|
26
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { filePreviewKind } from './file-pane-render.js';
|
|
2
|
+
import { iconHtml, refreshIcons } from './icons.js';
|
|
3
|
+
|
|
4
|
+
function button(label, icon, action) {
|
|
5
|
+
var element = document.createElement('button'); element.type = 'button'; element.title = label; element.setAttribute('aria-label', label);
|
|
6
|
+
element.innerHTML = icon ? iconHtml(icon) : label; element.addEventListener('click', action); return element;
|
|
7
|
+
}
|
|
8
|
+
export function filePaneShell(id, act) {
|
|
9
|
+
var panel = document.createElement('section'); panel.id = 'file-' + id; panel.className = 'file-instance'; panel.dataset.fileInstance = id;
|
|
10
|
+
var header = document.createElement('header'); header.className = 'tool-pane-header split-pane-header'; header.dataset.toolPane = panel.id;
|
|
11
|
+
var title = document.createElement('span'); title.className = 'tool-pane-title split-pane-title';
|
|
12
|
+
var space = document.createElement('span'); space.className = 'split-pane-drag-space';
|
|
13
|
+
var actions = document.createElement('div'); actions.className = 'file-viewer-window-actions';
|
|
14
|
+
var pin = button('Pin this file', 'pin', function () { act('pin'); }); pin.dataset.action = 'pin';
|
|
15
|
+
actions.append(pin, button('Expand file pane', 'maximize-2', function () { act('expand'); }), button('Close file pane', 'x', function () { act('close'); }));
|
|
16
|
+
header.append(title, space, actions);
|
|
17
|
+
var toolbar = document.createElement('div'); toolbar.className = 'file-instance-toolbar'; toolbar.setAttribute('aria-label', 'File actions');
|
|
18
|
+
['Preview', 'Source', 'History'].forEach(function (label) { var b = button(label, null, function () { act(label.toLowerCase()); }); b.dataset.action = label.toLowerCase(); toolbar.appendChild(b); });
|
|
19
|
+
var more = button('More file actions', 'ellipsis', toggle); more.setAttribute('aria-haspopup', 'menu'); more.setAttribute('aria-expanded', 'false');
|
|
20
|
+
toolbar.appendChild(more);
|
|
21
|
+
var menu = document.createElement('div'); menu.className = 'file-instance-more hidden'; menu.setAttribute('role', 'menu');
|
|
22
|
+
[['Copy source', 'copy'], ['Copy formatted', 'formatted'], ['Download', 'download'], ['Export PDF', 'pdf'], ['Present slides', 'slides'], ['Use H1 headings', 'h1'], ['Use H2 headings', 'h2'], ['Use H3 headings', 'h3'], ['Refresh', 'refresh']].forEach(function (item) {
|
|
23
|
+
var b = button(item[0], null, function () { dismiss(true); act(item[1]); }); b.setAttribute('role', 'menuitem'); b.dataset.action = item[1]; menu.appendChild(b);
|
|
24
|
+
});
|
|
25
|
+
function dismiss(focus) { menu.classList.add('hidden'); more.setAttribute('aria-expanded', 'false'); if (focus) more.focus(); }
|
|
26
|
+
function toggle() { var open = menu.classList.contains('hidden'); dismiss(false); if (open) { menu.classList.remove('hidden'); more.setAttribute('aria-expanded', 'true'); menu.querySelector('button:not(:disabled)').focus(); } }
|
|
27
|
+
function outside(event) { if (!menu.contains(event.target) && !more.contains(event.target)) dismiss(false); }
|
|
28
|
+
panel.addEventListener('keydown', function (event) {
|
|
29
|
+
if (!menu.classList.contains('hidden')) {
|
|
30
|
+
if (event.key === 'Escape' || event.key === 'Tab') { dismiss(event.key === 'Escape'); event.stopPropagation(); if (event.key === 'Escape') event.preventDefault(); }
|
|
31
|
+
if (event.key === 'ArrowDown' || event.key === 'ArrowUp' || event.key === 'Home' || event.key === 'End') {
|
|
32
|
+
var buttons = Array.from(menu.querySelectorAll('button:not(:disabled)')), index = buttons.indexOf(document.activeElement);
|
|
33
|
+
index = event.key === 'Home' ? 0 : event.key === 'End' ? buttons.length - 1 : (index + (event.key === 'ArrowDown' ? 1 : -1) + buttons.length) % buttons.length;
|
|
34
|
+
buttons[index].focus(); event.preventDefault(); event.stopPropagation();
|
|
35
|
+
}
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (event.key === 'Escape') { act('escape'); event.stopPropagation(); }
|
|
39
|
+
if (event.key === 'ArrowRight' || event.key === 'ArrowLeft') act(event.key === 'ArrowRight' ? 'next' : 'previous');
|
|
40
|
+
});
|
|
41
|
+
document.addEventListener('pointerdown', outside);
|
|
42
|
+
panel.addEventListener('clay-tool-pane-dispose', function () { document.removeEventListener('pointerdown', outside); }, { once: true });
|
|
43
|
+
var body = document.createElement('div'); body.className = 'file-viewer-body'; body.tabIndex = 0;
|
|
44
|
+
panel.append(header, toolbar, menu, body); refreshIcons(); return panel;
|
|
45
|
+
}
|
|
46
|
+
export function updateFilePaneToolbar(panel, state) {
|
|
47
|
+
var title = panel.querySelector('.tool-pane-title'); title.textContent = state.resource.path.split('/').pop(); title.title = state.resource.path;
|
|
48
|
+
var pin = panel.querySelector('[data-action="pin"]'), pinned = state.resource.mode === 'pin';
|
|
49
|
+
pin.setAttribute('aria-pressed', String(pinned)); pin.title = pinned ? 'Pinned to ' + state.resource.path + '. Switch to Follow selection' : 'Following file selection. Pin this file'; pin.setAttribute('aria-label', pinned ? 'Follow file selection' : 'Pin this file');
|
|
50
|
+
['preview', 'source', 'history'].forEach(function (key) { panel.querySelector('[data-action="' + key + '"]').setAttribute('aria-pressed', String(key === 'history' ? state.historyVisible : !state.historyVisible && (key === 'preview') === state.resource.rendered)); });
|
|
51
|
+
panel.querySelector('[data-action="preview"]').disabled = !filePreviewKind(state.resource.path) || !!state.binary;
|
|
52
|
+
var markdown = /\.mdx?$/i.test(state.resource.path);
|
|
53
|
+
['pdf', 'formatted', 'slides', 'h1', 'h2', 'h3'].forEach(function (key) { panel.querySelector('[data-action="' + key + '"]').disabled = !markdown; });
|
|
54
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { iconHtml } from './icons.js';
|
|
2
|
+
export function mapExtToLanguage(ext) {
|
|
3
|
+
var map = {
|
|
4
|
+
js: "javascript", ts: "typescript", jsx: "javascript", tsx: "typescript",
|
|
5
|
+
py: "python", rb: "ruby", go: "go", rs: "rust", java: "java",
|
|
6
|
+
css: "css", html: "xml", xml: "xml", json: "json", yaml: "yaml",
|
|
7
|
+
yml: "yaml", md: "markdown", sh: "bash", bash: "bash", zsh: "bash",
|
|
8
|
+
sql: "sql", c: "c", cpp: "cpp", h: "c", hpp: "cpp",
|
|
9
|
+
cs: "csharp", swift: "swift", kt: "kotlin", vue: "xml", svelte: "xml"
|
|
10
|
+
};
|
|
11
|
+
return map[ext] || null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function renderCodeWithLineNumbers(bodyEl, content, ext) {
|
|
15
|
+
var lang = mapExtToLanguage(ext);
|
|
16
|
+
var lines = content.split("\n");
|
|
17
|
+
var lineCount = lines.length;
|
|
18
|
+
|
|
19
|
+
var viewer = document.createElement("div");
|
|
20
|
+
viewer.className = "file-viewer-code";
|
|
21
|
+
|
|
22
|
+
var gutter = document.createElement("pre");
|
|
23
|
+
gutter.className = "file-viewer-gutter";
|
|
24
|
+
var nums = [];
|
|
25
|
+
for (var i = 1; i <= lineCount; i++) nums.push(i);
|
|
26
|
+
gutter.textContent = nums.join("\n");
|
|
27
|
+
|
|
28
|
+
var codeWrap = document.createElement("pre");
|
|
29
|
+
codeWrap.className = "file-viewer-code-content";
|
|
30
|
+
var codeEl = document.createElement("code");
|
|
31
|
+
if (lang) codeEl.className = "language-" + lang;
|
|
32
|
+
codeEl.textContent = content;
|
|
33
|
+
codeWrap.appendChild(codeEl);
|
|
34
|
+
|
|
35
|
+
viewer.appendChild(gutter);
|
|
36
|
+
viewer.appendChild(codeWrap);
|
|
37
|
+
|
|
38
|
+
bodyEl.innerHTML = "";
|
|
39
|
+
bodyEl.appendChild(viewer);
|
|
40
|
+
|
|
41
|
+
if (typeof hljs !== "undefined" && lang) {
|
|
42
|
+
hljs.highlightElement(codeEl);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function renderLargeTextFile(bodyEl, content, size) {
|
|
47
|
+
var viewer = document.createElement("div");
|
|
48
|
+
viewer.className = "file-viewer-large-text";
|
|
49
|
+
|
|
50
|
+
var notice = document.createElement("div");
|
|
51
|
+
notice.className = "file-viewer-large-notice";
|
|
52
|
+
notice.innerHTML = iconHtml("file-text") +
|
|
53
|
+
"<span>Large file (" + formatSize(size || 0) + ") — showing plain text for performance</span>";
|
|
54
|
+
|
|
55
|
+
var codeWrap = document.createElement("pre");
|
|
56
|
+
var codeEl = document.createElement("code");
|
|
57
|
+
codeEl.textContent = content;
|
|
58
|
+
codeWrap.appendChild(codeEl);
|
|
59
|
+
|
|
60
|
+
viewer.appendChild(notice);
|
|
61
|
+
viewer.appendChild(codeWrap);
|
|
62
|
+
bodyEl.innerHTML = "";
|
|
63
|
+
bodyEl.appendChild(viewer);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function formatSize(bytes) {
|
|
67
|
+
if (bytes < 1024) return bytes + " B";
|
|
68
|
+
if (bytes < 1048576) return (bytes / 1024).toFixed(1) + " KB";
|
|
69
|
+
return (bytes / 1048576).toFixed(1) + " MB";
|
|
70
|
+
}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { independentFilesActive, closeActiveFilePane, expandActiveFilePane, reopenIndependentFile, refreshIndependentFile, presentIndependentFile } from './file-pane-entrypoints.js';
|
|
2
|
+
import { openIndependentFile, routeFilePaneMessage } from './file-pane-instances.js';
|
|
3
|
+
import { activeSavedView } from './view-workspace-state.js';
|
|
4
|
+
import { mapExtToLanguage, renderCodeWithLineNumbers, renderLargeTextFile, formatSize } from './file-viewer-source.js';
|
|
1
5
|
import { presentedDocument, refreshPresentedDocument, closePresentedDocument } from './clay-studio-document.js';
|
|
2
6
|
import { registerStudioPaint } from './clay-studio-render.js';
|
|
3
7
|
import { iconHtml, refreshIcons } from './icons.js';
|
|
@@ -47,7 +51,7 @@ export function initFileBrowser(_ctx) {
|
|
|
47
51
|
onFocus: function(path) {
|
|
48
52
|
claimRightWorkbench("file-viewer");
|
|
49
53
|
ctx.fileViewerEl.classList.remove("hidden");
|
|
50
|
-
if (path !== currentFilePath || (store.get("fileViewerIsHtml") && isRendered && !
|
|
54
|
+
if (path !== currentFilePath || (store.get("fileViewerIsHtml") && isRendered && !ctx.fileViewerEl.querySelector(".file-viewer-html-preview"))) requestFileContent(path);
|
|
51
55
|
},
|
|
52
56
|
onEmpty: function() { resetMarkdownViewModes(); teardownFileViewer(); },
|
|
53
57
|
});
|
|
@@ -499,24 +503,30 @@ function ensureRenderedMarkdown() {
|
|
|
499
503
|
}
|
|
500
504
|
|
|
501
505
|
export function closeFileViewer() {
|
|
506
|
+
if (independentFilesActive()) return closeActiveFilePane();
|
|
502
507
|
releaseRightWorkbench("file-viewer");
|
|
503
508
|
teardownFileViewer();
|
|
504
509
|
}
|
|
505
510
|
|
|
506
511
|
function teardownFileViewer() {
|
|
507
512
|
cancelPlantUmlPreview();
|
|
508
|
-
var htmlFrame =
|
|
513
|
+
var htmlFrame = ctx.fileViewerEl.querySelector(".file-viewer-html-preview");
|
|
509
514
|
if (htmlFrame) htmlFrame.remove();
|
|
510
515
|
if (currentFilePath && isFollowingMarkdown(currentFilePath)) cancelMarkdownFollow();
|
|
511
516
|
sendUnwatch();
|
|
512
517
|
inlineDiffActive = false;
|
|
513
518
|
exitMarkdownSlides();
|
|
514
519
|
ctx.fileViewerEl.classList.remove("file-viewer-wide");
|
|
515
|
-
|
|
520
|
+
setLegacyFileViewerFullscreen(false);
|
|
516
521
|
ctx.fileViewerEl.classList.add("hidden");
|
|
517
522
|
}
|
|
518
523
|
|
|
519
524
|
export function setFileViewerFullscreen(enabled) {
|
|
525
|
+
if (independentFilesActive()) return expandActiveFilePane(enabled);
|
|
526
|
+
return setLegacyFileViewerFullscreen(enabled);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
function setLegacyFileViewerFullscreen(enabled) {
|
|
520
530
|
var isFullscreen = !!enabled;
|
|
521
531
|
var viewer = ctx && ctx.fileViewerEl ? ctx.fileViewerEl : document.getElementById("file-viewer");
|
|
522
532
|
var button = document.getElementById("file-viewer-fullscreen");
|
|
@@ -575,6 +585,11 @@ var pendingRenderedOpen = false;
|
|
|
575
585
|
|
|
576
586
|
export function openFile(filePath, opts) {
|
|
577
587
|
if (!filePath) return;
|
|
588
|
+
if (activeSavedView() && !store.get('paneMode')) {
|
|
589
|
+
var opened = openIndependentFile(filePath, opts);
|
|
590
|
+
if (opened !== false) closePresentedDocument();
|
|
591
|
+
return opened;
|
|
592
|
+
}
|
|
578
593
|
var state = store.snap();
|
|
579
594
|
if (!state.connected) return false;
|
|
580
595
|
if (opts && opts.projectSlug && opts.projectSlug !== state.currentSlug) return false;
|
|
@@ -597,6 +612,7 @@ export function openFile(filePath, opts) {
|
|
|
597
612
|
}
|
|
598
613
|
|
|
599
614
|
export function reopenFileViewer() {
|
|
615
|
+
if (independentFilesActive()) return reopenIndependentFile();
|
|
600
616
|
var workbenchRevision = claimRightWorkbench("file-viewer");
|
|
601
617
|
store.set({ fileViewerOpenRevision: workbenchRevision });
|
|
602
618
|
if (!focusedFileViewerTab()) return false;
|
|
@@ -616,6 +632,7 @@ export function reopenFileViewer() {
|
|
|
616
632
|
|
|
617
633
|
export function openWorkingTreeDiff(diff) {
|
|
618
634
|
if (!diff || !diff.path) return;
|
|
635
|
+
if (independentFilesActive()) return presentIndependentFile({ path: diff.path, content: diff.newContent, binary: diff.binary }, diff.binary ? null : { oldStr: diff.oldContent || "", newStr: diff.newContent || "" }, diff.review);
|
|
619
636
|
var workbenchRevision = claimRightWorkbench("file-viewer");
|
|
620
637
|
store.set({ fileViewerOpenRevision: workbenchRevision });
|
|
621
638
|
openFileViewerTab(diff.path);
|
|
@@ -636,6 +653,7 @@ export function openWorkingTreeDiff(diff) {
|
|
|
636
653
|
|
|
637
654
|
export function presentMarkdownEdit(msg) {
|
|
638
655
|
if (!msg || !beginMarkdownPresentation(msg.path)) return;
|
|
656
|
+
if (independentFilesActive()) return presentIndependentFile(msg);
|
|
639
657
|
var workbenchRevision = claimRightWorkbench("file-viewer");
|
|
640
658
|
store.set({ fileViewerOpenRevision: workbenchRevision });
|
|
641
659
|
openFileViewerTab(msg.path, { content: msg.content });
|
|
@@ -739,7 +757,7 @@ function requestFileContent(filePath) {
|
|
|
739
757
|
if (refreshPresentedDocument(filePath)) return;
|
|
740
758
|
var requestId = "file-read-" + Date.now() + "-" + Math.random().toString(36).slice(2);
|
|
741
759
|
var state = store.snap();
|
|
742
|
-
store.set({ fileReadRequest: { requestId: requestId, path: filePath, projectSlug: state.currentSlug || null, sessionId: state.activeSessionId != null ? String(state.activeSessionId) : null, accountId: state.myUserId || null, workbenchRevision: rightWorkbenchRevisionFor('file-viewer') } });
|
|
760
|
+
store.set({ fileReadRequest: { requestId: requestId, path: filePath, projectSlug: state.currentSlug || null, sessionId: state.activeSessionId != null ? String(state.activeSessionId) : null, accountId: state.myUserId || null, viewId: state.projectSplitViewActiveId || null, socketGeneration: state.projectSplitViewSocketGeneration, workbenchRevision: rightWorkbenchRevisionFor('file-viewer') } });
|
|
743
761
|
var pending = store.get('pendingFileNavigation');
|
|
744
762
|
if (pending && pending.path === filePath) store.set({ pendingFileNavigation: Object.assign({}, pending, { requestId: requestId }) });
|
|
745
763
|
if (ctx.ws && ctx.connected) {
|
|
@@ -750,6 +768,7 @@ function requestFileContent(filePath) {
|
|
|
750
768
|
var pendingRefresh = false;
|
|
751
769
|
|
|
752
770
|
export function refreshIfOpen(filePath) {
|
|
771
|
+
if (independentFilesActive()) return refreshIndependentFile(filePath);
|
|
753
772
|
if (!currentFilePath || ctx.fileViewerEl.classList.contains("hidden")) return;
|
|
754
773
|
// Don't refresh while history panel or inline diff is showing
|
|
755
774
|
if (historyVisible || inlineDiffActive) return;
|
|
@@ -863,7 +882,7 @@ function renderFilteredTree(container, tree, depth, query) {
|
|
|
863
882
|
(function (rowEl, childEl, folderName) {
|
|
864
883
|
rowEl.addEventListener("click", function (e) {
|
|
865
884
|
e.stopPropagation();
|
|
866
|
-
claimRightWorkbench("file-viewer");
|
|
885
|
+
if (!activeSavedView()) claimRightWorkbench("file-viewer");
|
|
867
886
|
var isExpanded = rowEl.classList.contains("expanded");
|
|
868
887
|
rowEl.classList.toggle("expanded");
|
|
869
888
|
childEl.classList.toggle("hidden", isExpanded);
|
|
@@ -886,6 +905,11 @@ function renderFilteredTree(container, tree, depth, query) {
|
|
|
886
905
|
(function (filePath, rowEl) {
|
|
887
906
|
rowEl.addEventListener("click", function (e) {
|
|
888
907
|
e.stopPropagation();
|
|
908
|
+
if (activeSavedView() && !store.get('paneMode')) {
|
|
909
|
+
openIndependentFile(filePath);
|
|
910
|
+
if (window.innerWidth <= 768) closeSidebar();
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
889
913
|
claimRightWorkbench("file-viewer");
|
|
890
914
|
if (followedFileChanged(filePath)) cancelMarkdownFollow();
|
|
891
915
|
var prev = ctx.fileTreeEl.querySelector(".file-tree-item.active");
|
|
@@ -1018,8 +1042,10 @@ function restoreExpanded(expandedSet) {
|
|
|
1018
1042
|
}
|
|
1019
1043
|
|
|
1020
1044
|
export function handleFsRead(msg) {
|
|
1045
|
+
if (routeFilePaneMessage(msg)) return;
|
|
1021
1046
|
var request = store.get('fileReadRequest');
|
|
1022
1047
|
var state = store.snap();
|
|
1048
|
+
if (request && (request.viewId !== (state.projectSplitViewActiveId || null) || request.socketGeneration !== state.projectSplitViewSocketGeneration)) return;
|
|
1023
1049
|
if (!request || !state.connected || msg.requestId !== request.requestId || msg.path !== request.path) return;
|
|
1024
1050
|
if ((request.projectSlug || null) !== (state.currentSlug || null)) return;
|
|
1025
1051
|
if ((request.sessionId || null) !== (state.activeSessionId == null ? null : String(state.activeSessionId))) return;
|
|
@@ -1094,7 +1120,7 @@ function renderEntries(container, entries, depth) {
|
|
|
1094
1120
|
(function (dirPath, childEl, rowEl, folderName) {
|
|
1095
1121
|
rowEl.addEventListener("click", function (e) {
|
|
1096
1122
|
e.stopPropagation();
|
|
1097
|
-
claimRightWorkbench("file-viewer");
|
|
1123
|
+
if (!activeSavedView()) claimRightWorkbench("file-viewer");
|
|
1098
1124
|
var isExpanded = rowEl.classList.contains("expanded");
|
|
1099
1125
|
if (isExpanded) {
|
|
1100
1126
|
rowEl.classList.remove("expanded");
|
|
@@ -1134,6 +1160,11 @@ function renderEntries(container, entries, depth) {
|
|
|
1134
1160
|
(function (filePath, rowEl) {
|
|
1135
1161
|
rowEl.addEventListener("click", function (e) {
|
|
1136
1162
|
e.stopPropagation();
|
|
1163
|
+
if (activeSavedView() && !store.get('paneMode')) {
|
|
1164
|
+
openIndependentFile(filePath);
|
|
1165
|
+
if (window.innerWidth <= 768) closeSidebar();
|
|
1166
|
+
return;
|
|
1167
|
+
}
|
|
1137
1168
|
claimRightWorkbench("file-viewer");
|
|
1138
1169
|
if (followedFileChanged(filePath)) cancelMarkdownFollow();
|
|
1139
1170
|
// Mark active
|
|
@@ -1382,6 +1413,7 @@ function pathsReferToSameFile(left, right) {
|
|
|
1382
1413
|
}
|
|
1383
1414
|
|
|
1384
1415
|
export function handleFileChanged(msg, presentedSource) {
|
|
1416
|
+
if (routeFilePaneMessage(msg)) return;
|
|
1385
1417
|
var source = store.get('studioDocumentView');
|
|
1386
1418
|
if (source && source.descriptor.path === msg.path && (!presentedSource || presentedDocument(msg.path) !== presentedSource)) return;
|
|
1387
1419
|
if (!msg.path || !pathsReferToSameFile(msg.path, currentFilePath)) return;
|
|
@@ -1545,81 +1577,7 @@ function showInlineDiff(oldStr, newStr, review) {
|
|
|
1545
1577
|
render();
|
|
1546
1578
|
}
|
|
1547
1579
|
|
|
1548
|
-
function mapExtToLanguage(
|
|
1549
|
-
var map = {
|
|
1550
|
-
js: "javascript", ts: "typescript", jsx: "javascript", tsx: "typescript",
|
|
1551
|
-
py: "python", rb: "ruby", go: "go", rs: "rust", java: "java",
|
|
1552
|
-
css: "css", html: "xml", xml: "xml", json: "json", yaml: "yaml",
|
|
1553
|
-
yml: "yaml", md: "markdown", sh: "bash", bash: "bash", zsh: "bash",
|
|
1554
|
-
sql: "sql", c: "c", cpp: "cpp", h: "c", hpp: "cpp",
|
|
1555
|
-
cs: "csharp", swift: "swift", kt: "kotlin", vue: "xml", svelte: "xml"
|
|
1556
|
-
};
|
|
1557
|
-
return map[ext] || null;
|
|
1558
|
-
}
|
|
1559
|
-
|
|
1560
|
-
function currentLang() {
|
|
1561
|
-
if (!currentFilePath) return null;
|
|
1562
|
-
var ext = currentFilePath.split(".").pop().toLowerCase();
|
|
1563
|
-
return mapExtToLanguage(ext);
|
|
1564
|
-
}
|
|
1565
|
-
|
|
1566
|
-
function renderCodeWithLineNumbers(bodyEl, content, ext) {
|
|
1567
|
-
var lang = mapExtToLanguage(ext);
|
|
1568
|
-
var lines = content.split("\n");
|
|
1569
|
-
var lineCount = lines.length;
|
|
1570
|
-
|
|
1571
|
-
var viewer = document.createElement("div");
|
|
1572
|
-
viewer.className = "file-viewer-code";
|
|
1573
|
-
|
|
1574
|
-
var gutter = document.createElement("pre");
|
|
1575
|
-
gutter.className = "file-viewer-gutter";
|
|
1576
|
-
var nums = [];
|
|
1577
|
-
for (var i = 1; i <= lineCount; i++) nums.push(i);
|
|
1578
|
-
gutter.textContent = nums.join("\n");
|
|
1579
|
-
|
|
1580
|
-
var codeWrap = document.createElement("pre");
|
|
1581
|
-
codeWrap.className = "file-viewer-code-content";
|
|
1582
|
-
var codeEl = document.createElement("code");
|
|
1583
|
-
if (lang) codeEl.className = "language-" + lang;
|
|
1584
|
-
codeEl.textContent = content;
|
|
1585
|
-
codeWrap.appendChild(codeEl);
|
|
1586
|
-
|
|
1587
|
-
viewer.appendChild(gutter);
|
|
1588
|
-
viewer.appendChild(codeWrap);
|
|
1589
|
-
|
|
1590
|
-
bodyEl.innerHTML = "";
|
|
1591
|
-
bodyEl.appendChild(viewer);
|
|
1592
|
-
|
|
1593
|
-
if (typeof hljs !== "undefined" && lang) {
|
|
1594
|
-
hljs.highlightElement(codeEl);
|
|
1595
|
-
}
|
|
1596
|
-
}
|
|
1597
|
-
|
|
1598
|
-
function renderLargeTextFile(bodyEl, content, size) {
|
|
1599
|
-
var viewer = document.createElement("div");
|
|
1600
|
-
viewer.className = "file-viewer-large-text";
|
|
1601
|
-
|
|
1602
|
-
var notice = document.createElement("div");
|
|
1603
|
-
notice.className = "file-viewer-large-notice";
|
|
1604
|
-
notice.innerHTML = iconHtml("file-text") +
|
|
1605
|
-
"<span>Large file (" + formatSize(size || 0) + ") — showing plain text for performance</span>";
|
|
1606
|
-
|
|
1607
|
-
var codeWrap = document.createElement("pre");
|
|
1608
|
-
var codeEl = document.createElement("code");
|
|
1609
|
-
codeEl.textContent = content;
|
|
1610
|
-
codeWrap.appendChild(codeEl);
|
|
1611
|
-
|
|
1612
|
-
viewer.appendChild(notice);
|
|
1613
|
-
viewer.appendChild(codeWrap);
|
|
1614
|
-
bodyEl.innerHTML = "";
|
|
1615
|
-
bodyEl.appendChild(viewer);
|
|
1616
|
-
}
|
|
1617
|
-
|
|
1618
|
-
function formatSize(bytes) {
|
|
1619
|
-
if (bytes < 1024) return bytes + " B";
|
|
1620
|
-
if (bytes < 1048576) return (bytes / 1024).toFixed(1) + " KB";
|
|
1621
|
-
return (bytes / 1048576).toFixed(1) + " MB";
|
|
1622
|
-
}
|
|
1580
|
+
function currentLang() { return currentFilePath ? mapExtToLanguage(currentFilePath.split('.').pop().toLowerCase()) : null; }
|
|
1623
1581
|
|
|
1624
1582
|
// --- File edit history ---
|
|
1625
1583
|
|
|
@@ -1639,6 +1597,7 @@ function requestGitDiff(hash, hash2) {
|
|
|
1639
1597
|
}
|
|
1640
1598
|
|
|
1641
1599
|
export function handleFileHistory(msg) {
|
|
1600
|
+
if (routeFilePaneMessage(msg)) return;
|
|
1642
1601
|
currentHistoryEntries = msg.entries || [];
|
|
1643
1602
|
var historyBtn = document.getElementById("file-viewer-history");
|
|
1644
1603
|
|
|
@@ -1655,6 +1614,7 @@ export function handleFileHistory(msg) {
|
|
|
1655
1614
|
}
|
|
1656
1615
|
|
|
1657
1616
|
export function handleGitDiff(msg) {
|
|
1617
|
+
if (routeFilePaneMessage(msg)) return;
|
|
1658
1618
|
if (msg.hash && msg.diff !== undefined) {
|
|
1659
1619
|
var key = msg.hash2 ? msg.hash + ".." + msg.hash2 : msg.hash;
|
|
1660
1620
|
gitDiffCache[key] = msg.diff;
|
|
@@ -1673,6 +1633,7 @@ function requestFileAt(hash) {
|
|
|
1673
1633
|
}
|
|
1674
1634
|
|
|
1675
1635
|
export function handleFileAt(msg) {
|
|
1636
|
+
if (routeFilePaneMessage(msg)) return;
|
|
1676
1637
|
if (msg.hash && msg.content !== undefined) {
|
|
1677
1638
|
fileAtCache[msg.hash] = msg.content;
|
|
1678
1639
|
}
|
|
@@ -2370,7 +2331,7 @@ function renderViewFileContent(entry, content) {
|
|
|
2370
2331
|
bodyEl.appendChild(codeContainer);
|
|
2371
2332
|
}
|
|
2372
2333
|
|
|
2373
|
-
function navigateToEdit(edit) {
|
|
2334
|
+
export function navigateToEdit(edit) {
|
|
2374
2335
|
// If already in the same session, scroll directly without replaying history
|
|
2375
2336
|
if (ctx.activeSessionId === edit.sessionLocalId) {
|
|
2376
2337
|
scrollToToolElement(edit.toolId, edit.assistantUuid);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { fileEntryContext } from './file-pane-entrypoints.js';
|
|
1
2
|
import { currentGithubWorkMarkup, refreshGithubWork, resetGithubWork } from './session-github.js';
|
|
2
3
|
import { store } from './store.js';
|
|
3
4
|
import { refreshIcons, iconHtml } from './icons.js';
|
|
@@ -332,7 +333,9 @@ function runAction(action, paths) {
|
|
|
332
333
|
}
|
|
333
334
|
|
|
334
335
|
function openFileDiff(filePath, reviewIndex) {
|
|
336
|
+
var receipt = fileEntryContext();
|
|
335
337
|
requestJson(apiPath("file-diff?path=" + encodeURIComponent(filePath)), { cache: "no-store" }).then(function (result) {
|
|
338
|
+
if (receipt !== fileEntryContext()) return;
|
|
336
339
|
var paths = currentStatus ? currentStatus.files.map(function (file) { return file.path; }) : [filePath];
|
|
337
340
|
var index = typeof reviewIndex === "number" ? reviewIndex : paths.indexOf(filePath);
|
|
338
341
|
if (index < 0) index = 0;
|
|
@@ -350,8 +353,10 @@ function openFileDiff(filePath, reviewIndex) {
|
|
|
350
353
|
}
|
|
351
354
|
|
|
352
355
|
function openSessionDiff(sessionKey, filePath) {
|
|
356
|
+
var receipt = fileEntryContext();
|
|
353
357
|
var url = apiPath("session-diff?session=" + encodeURIComponent(sessionKey) + "&path=" + encodeURIComponent(filePath));
|
|
354
358
|
requestJson(url, { cache: "no-store" }).then(function (result) {
|
|
359
|
+
if (receipt !== fileEntryContext()) return;
|
|
355
360
|
openWorkingTreeDiff(result);
|
|
356
361
|
showToast("Compared with start of " + (result.sessionTitle || "session"));
|
|
357
362
|
}).catch(function (err) {
|
|
@@ -2,7 +2,7 @@ import { openLinear, initLinearPanel } from './linear-panel.js';
|
|
|
2
2
|
import { store } from './store.js';
|
|
3
3
|
import { getWs } from './ws-ref.js';
|
|
4
4
|
import { showToast } from './utils.js';
|
|
5
|
-
import { claimRightWorkbench, registerRightWorkbench, releaseRightWorkbench } from './right-workbench.js';
|
|
5
|
+
import { handlesWorkbenchKey, claimRightWorkbench, registerRightWorkbench, releaseRightWorkbench } from './right-workbench.js';
|
|
6
6
|
import { refreshIcons } from './icons.js';
|
|
7
7
|
import { enhanceClayLogLinks } from './clay-log-links.js';
|
|
8
8
|
import { updateIssueLink } from './clay-issue-links.js';
|
|
@@ -169,7 +169,7 @@ export function initIssues() {
|
|
|
169
169
|
registerRightWorkbench("issues", closeIssues);
|
|
170
170
|
var el = document.createElement('section');
|
|
171
171
|
el.id = 'issues-panel'; el.className = 'hidden'; el.setAttribute('aria-label', 'Project Issues');
|
|
172
|
-
el.innerHTML = '<header class="issues-topbar"><button class="issues-icon-btn" data-issues-back aria-label="Back to issues" title="Back to issue list"><i data-lucide="arrow-left"></i></button><span class="issues-title"><i data-lucide="circle-dot"></i>Issues</span><span class="issues-subtitle">Manage issues through Driver chat.</span><
|
|
172
|
+
el.innerHTML = '<header class="issues-topbar"><button class="issues-icon-btn" data-issues-back aria-label="Back to issues" title="Back to issue list"><i data-lucide="arrow-left"></i></button><span class="issues-title"><i data-lucide="circle-dot"></i>Issues</span><span class="issues-subtitle">Manage issues through Driver chat.</span><div class="issues-window-actions"><button class="issues-icon-btn" data-issues-wide aria-label="Widen Issues" title="Widen Issues" aria-pressed="false"><i data-lucide="chevrons-left-right"></i></button><button class="issues-icon-btn" data-issues-full aria-label="Toggle Issues fullscreen" title="Toggle fullscreen" aria-pressed="false"><i data-lucide="maximize-2"></i></button><button class="issues-icon-btn" data-issues-close aria-label="Close Issues" title="Close Issues"><i data-lucide="x"></i></button></div></header><div class="issues-filters"><label class="issues-search"><i data-lucide="search"></i><input name="query" type="search" placeholder="Search issues" aria-label="Search issues"></label><select name="filter-status" aria-label="Filter status"><option value="">All statuses</option><option value="open">Open</option><option value="in_progress">In progress</option><option value="resolved">Resolved</option><option value="closed">Closed</option></select><select name="filter-type" aria-label="Filter type"><option value="">All types</option><option value="bug">Bug</option><option value="feature">Feature</option><option value="plan">Plan</option></select><button type="button" class="issues-linear-link" data-open-linear title="Open Linear" aria-label="Open Linear">Linear<i data-lucide="chevron-right"></i></button></div><p class="issues-notice" role="status"></p><main class="issues-content" role="region" aria-live="polite"></main><div class="issues-delete-dialog hidden" role="dialog" aria-modal="true" aria-labelledby="issues-delete-heading"><div class="issues-delete-card"><h2 id="issues-delete-heading">Delete this issue?</h2><p>This removes the issue from the board but preserves its history.</p><p class="issues-delete-title"></p><p class="issues-delete-status" role="status"></p><div><button type="button" data-issue-delete-cancel>Cancel</button><button type="button" data-issue-delete-confirm>Delete issue</button></div></div></div>';
|
|
173
173
|
host.appendChild(el);
|
|
174
174
|
el.querySelector('[data-open-linear]').addEventListener('click', function () { openLinear(); });
|
|
175
175
|
el.addEventListener('input', handleIssueGithubInput);
|
|
@@ -226,9 +226,8 @@ export function initIssues() {
|
|
|
226
226
|
});
|
|
227
227
|
store.subscribe(function (state, previous) {
|
|
228
228
|
if (state.currentSlug !== previous.currentSlug || (previous.connected && !state.connected)) { closeIssues(); store.set({ issuesRequests: {}, issuesSelected: null, issuesCache: {}, issuesMutationRequest: null }); }
|
|
229
|
-
if (state.issuesOpen && (state.projectLogsOpen || state.scheduledTasksOpen)) closeIssues();
|
|
230
229
|
});
|
|
231
|
-
document.addEventListener('keydown', function (event) { if (store.get('issuesOpen')) { deleteDialogKeydown(event); if (!event.defaultPrevented && event.key === 'Escape') closeIssues(); } });
|
|
230
|
+
document.addEventListener('keydown', function (event) { if (store.get('issuesOpen') && handlesWorkbenchKey('issues', event)) { deleteDialogKeydown(event); if (!event.defaultPrevented && event.key === 'Escape') closeIssues(); } });
|
|
232
231
|
}
|
|
233
232
|
function showIssueEdit(entry) {
|
|
234
233
|
if (!entry) return;
|
|
@@ -4,7 +4,7 @@ import { escapeHtml } from './utils.js';
|
|
|
4
4
|
import { renderMarkdown } from './markdown.js';
|
|
5
5
|
import { refreshIcons } from './icons.js';
|
|
6
6
|
import { linearIconMarkup } from './session-github.js';
|
|
7
|
-
import { claimRightWorkbench, registerRightWorkbench, releaseRightWorkbench } from './right-workbench.js';
|
|
7
|
+
import { handlesWorkbenchKey, claimRightWorkbench, registerRightWorkbench, releaseRightWorkbench } from './right-workbench.js';
|
|
8
8
|
|
|
9
9
|
function esc(value) { return escapeHtml(String(value || '')).replace(/"/g, '"').replace(/'/g, '''); }
|
|
10
10
|
function panel() { return document.getElementById('linear-panel'); }
|
|
@@ -145,7 +145,7 @@ export function initLinearPanel() {
|
|
|
145
145
|
else if (issue && button.hasAttribute('data-linear-start')) { button.disabled = true; request('linear_start_work', { url: issue.url }); }
|
|
146
146
|
else if (issue && button.hasAttribute('data-linear-more')) { button.disabled = true; request('linear_read', { url: issue.url, cursor: issue.pageInfo.endCursor }); }
|
|
147
147
|
});
|
|
148
|
-
document.addEventListener('keydown', function (event) { if (event.key === 'Escape' && store.get('linearOpen')) closeLinear(); });
|
|
148
|
+
document.addEventListener('keydown', function (event) { if (event.key === 'Escape' && store.get('linearOpen') && handlesWorkbenchKey('linear', event)) closeLinear(); });
|
|
149
149
|
store.subscribe(function (state, previous) {
|
|
150
150
|
if (state.currentSlug !== previous.currentSlug || state.myUserId !== previous.myUserId || state.dmMode !== previous.dmMode || (previous.connected && !state.connected)) closeLinear();
|
|
151
151
|
else if (state.linearOpen && (state.githubWorkSessions !== previous.githubWorkSessions || state.activeSessionId !== previous.activeSessionId) && state.linearIssue) renderIssue();
|
|
@@ -103,7 +103,7 @@ function bindPanel() {
|
|
|
103
103
|
panel.querySelector('[data-knowledge-forward]').addEventListener('click', function () { navigateHistory('forward'); });
|
|
104
104
|
panel.querySelector('.knowledge-search input').addEventListener('input', scheduleSearch);
|
|
105
105
|
panel.querySelector('[data-knowledge-wide]').addEventListener('click', function () { var key = workspaceKey(); patchState(key, { wide: !stateFor(key).wide }); renderShell(); });
|
|
106
|
-
panel.querySelector('[data-knowledge-full]').addEventListener('click',
|
|
106
|
+
panel.querySelector('[data-knowledge-full]').addEventListener('click', togglePaneExpansion);
|
|
107
107
|
panel.querySelector('[data-delete-cancel]').addEventListener('click', closeDelete);
|
|
108
108
|
panel.querySelector('[data-delete-confirm]').addEventListener('click', confirmDelete);
|
|
109
109
|
panel.addEventListener('click', handlePanelClick);
|
|
@@ -326,10 +326,14 @@ function retrySync() {
|
|
|
326
326
|
simpleRequest('knowledge_sync', { names: retry.names }, { syncRetry: retry });
|
|
327
327
|
}
|
|
328
328
|
|
|
329
|
+
function togglePaneExpansion() { var key = workspaceKey(), state = stateFor(key);
|
|
330
|
+
if (state.fullscreen) { patchState(key, { paneExpanded: false }); exitEditor(); return; }
|
|
331
|
+
patchState(key, { paneExpanded: !state.paneExpanded }); renderShell();
|
|
332
|
+
}
|
|
329
333
|
function renderShell() {
|
|
330
|
-
var state = stateFor(workspaceKey()); panel.classList.toggle('knowledge-wide', state.wide); panel.classList.toggle('panel-fullscreen', state.fullscreen);
|
|
331
|
-
panel.querySelector('[data-knowledge-wide]').setAttribute('aria-pressed', String(state.wide)); panel.querySelector('[data-knowledge-full]').setAttribute('aria-pressed', String(state.fullscreen));
|
|
332
|
-
panel.querySelector('[data-knowledge-full]').hidden =
|
|
334
|
+
var state = stateFor(workspaceKey()); panel.classList.toggle('knowledge-wide', state.wide); panel.classList.toggle('panel-fullscreen', !!(state.fullscreen || state.paneExpanded));
|
|
335
|
+
panel.querySelector('[data-knowledge-wide]').setAttribute('aria-pressed', String(state.wide)); panel.querySelector('[data-knowledge-full]').setAttribute('aria-pressed', String(!!(state.fullscreen || state.paneExpanded)));
|
|
336
|
+
panel.querySelector('[data-knowledge-full]').hidden = false; panel.querySelector('[data-knowledge-wide]').hidden = state.fullscreen;
|
|
333
337
|
panel.querySelector('[data-knowledge-back]').disabled = !(state.navigationBack || []).length; panel.querySelector('[data-knowledge-forward]').disabled = !(state.navigationForward || []).length;
|
|
334
338
|
}
|
|
335
339
|
function renderStatus() {
|
|
@@ -433,12 +437,12 @@ export function openKnowledgeWorkbench() {
|
|
|
433
437
|
ensurePanel(); if (!panel || !isMateWorkspace(store.snap())) return; returnFocus = document.activeElement;
|
|
434
438
|
claimRightWorkbench('mate-knowledge'); panel.classList.remove('hidden'); setKnowledgeNarrowBackground(panel, true); var button = document.getElementById('knowledge-workbench-btn'); if (button) button.classList.add('active');
|
|
435
439
|
var key = workspaceKey(); var state = stateFor(key); var drafts = Object.assign({}, state.drafts); if (state.selected && drafts[state.selected]) drafts[state.selected] = Object.assign({}, drafts[state.selected], { mode: 'read' });
|
|
436
|
-
setState(key, Object.assign({}, state, { drafts: drafts, fullscreen: false, loading: true, error: '' })); simpleRequest('knowledge_list'); if (stateFor(key).query.trim()) { patchState(key, { searching: true }); requestSearch(key, stateFor(key).query, 0, false); } render(); setTimeout(function () { var search = panel.querySelector('.knowledge-search input'); if (search) search.focus(); }, 0);
|
|
440
|
+
setState(key, Object.assign({}, state, { drafts: drafts, fullscreen: false, paneExpanded: false, loading: true, error: '' })); simpleRequest('knowledge_list'); if (stateFor(key).query.trim()) { patchState(key, { searching: true }); requestSearch(key, stateFor(key).query, 0, false); } render(); setTimeout(function () { var search = panel.querySelector('.knowledge-search input'); if (search) search.focus(); }, 0);
|
|
437
441
|
}
|
|
438
442
|
export function closeKnowledgeWorkbench(skipSave) {
|
|
439
443
|
if (!panel) return; var active = document.activeElement; var shouldReturn = skipSave !== true && (!active || active === document.body || panel.contains(active));
|
|
440
444
|
var key = workspaceKey(); cancelScheduledSearch(); if (deleteTarget) closeDelete(); if (skipSave !== true) { saveScroll(); var selected = stateFor(key).selected; if (selected) saveDraftNow(key, selected); }
|
|
441
|
-
patchState(key, { fullscreen: false }); destroyKnowledgeEditor(); panel.classList.add('hidden'); setKnowledgeNarrowBackground(panel, false); releaseRightWorkbench('mate-knowledge');
|
|
445
|
+
patchState(key, { fullscreen: false, paneExpanded: false }); destroyKnowledgeEditor(); panel.classList.add('hidden'); setKnowledgeNarrowBackground(panel, false); releaseRightWorkbench('mate-knowledge');
|
|
442
446
|
var button = document.getElementById('knowledge-workbench-btn'); if (button) button.classList.remove('active'); if (shouldReturn && returnFocus && returnFocus.isConnected) returnFocus.focus(); returnFocus = null;
|
|
443
447
|
}
|
|
444
448
|
export function initMateKnowledgeWorkbench() {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { store } from './store.js';
|
|
1
2
|
import { initNotificationSettings, saveNotificationPreference, updatePushSettings } from './notification-settings.js';
|
|
2
3
|
import { initExtensionSettings } from './extension-settings.js';
|
|
3
4
|
import { copyToClipboard, showToast } from './utils.js';
|
|
@@ -71,7 +72,9 @@ export function initNotifications(_ctx) {
|
|
|
71
72
|
var $ = ctx.$;
|
|
72
73
|
|
|
73
74
|
// --- Mobile viewport (iOS keyboard handling) ---
|
|
74
|
-
|
|
75
|
+
// Embedded panes follow the host viewport. Their layout resize is not a
|
|
76
|
+
// software keyboard opening and must not force the transcript to its tail.
|
|
77
|
+
if (window.visualViewport && !store.get('paneMode')) {
|
|
75
78
|
var layout = $("layout");
|
|
76
79
|
var mobileTabBar = document.getElementById("mobile-tab-bar");
|
|
77
80
|
var keyboardWasOpen = false;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { paneHeaderRuntime, initPaneHeaderRuntime } from './pane-header-runtime.js';
|
|
2
|
+
import { sendBoundBrowserCommand } from './pane-browser-transport.js';
|
|
2
3
|
import { disarmStickyBottom } from './chat-render-runtime.js';
|
|
3
4
|
import { store } from './store.js';
|
|
4
5
|
import { getWs } from './ws-ref.js';
|
|
@@ -206,6 +207,7 @@ export function initPaneActivation() {
|
|
|
206
207
|
binding: binding, ready: store.get('connected') && store.get('paneReady') && !store.get('paneSuspended') };
|
|
207
208
|
},
|
|
208
209
|
headerRuntime: paneHeaderRuntime,
|
|
210
|
+
browserCommand: sendBoundBrowserCommand,
|
|
209
211
|
activate: activatePaneSession,
|
|
210
212
|
checkDraft: function () { if (!store.get('panePendingBinding')) { var draft = takeComposerDraft(); restoreComposerDraft(draft); } },
|
|
211
213
|
suspend: suspendPane,
|
|
@@ -63,7 +63,11 @@ export function livePaneBinding(frame, message) {
|
|
|
63
63
|
var target = live && paneTarget(state, state.paneBindingSessions || [], live.sessionId);
|
|
64
64
|
var inLegacySplit = !!(live && split && split.panes.some(function (pane) { return pane.slug === live.projectSlug && pane.sessionId === live.sessionId; }));
|
|
65
65
|
var activePresentation = (state.projectSplitViews || []).find(function (view) { return view.id === state.projectSplitViewActiveId; });
|
|
66
|
-
var
|
|
66
|
+
var pair = activePresentation && activePresentation.workspace && activePresentation.workspace.linkedPair;
|
|
67
|
+
var linkedPresentation = !!(split && pair && split.groupId === pair.groupId && (state.splitGroups || []).some(function (group) {
|
|
68
|
+
return group.id === pair.groupId && group.pair && (state.paneBindingSessions || []).some(function (session) { return session.id === group.pair.driverId && session.sessionOriginId === pair.driverOriginId; });
|
|
69
|
+
}));
|
|
70
|
+
var inPresentation = !!(live && live.binding && (!split || linkedPresentation) && activePresentation && activePresentation.sessions.some(function (session) {
|
|
67
71
|
return session.id === live.sessionId && session.sessionOriginId === live.binding.sessionOriginId;
|
|
68
72
|
}));
|
|
69
73
|
var inSingletonPresentation = !!(live && live.binding && !split && !activePresentation &&
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { store } from './store.js';
|
|
2
|
+
import { selectBrowserPane } from './pane-browser-transport.js';
|
|
2
3
|
import { livePaneBinding, paneMessageBinding } from './pane-binding.js';
|
|
3
4
|
import { showToast } from './utils.js';
|
|
4
5
|
|
|
@@ -15,7 +16,7 @@ export function handlePaneBrowserMessage(event, host) {
|
|
|
15
16
|
if (!s.connected || !pane || msg.projectSlug !== s.currentSlug || msg.projectSlug !== frame.dataset.projectSlug || String(msg.sessionId) !== frame.dataset.sessionId) return true;
|
|
16
17
|
var expected = new URL('/p/' + encodeURIComponent(pane.slug) + '/?pane=1&session=' + encodeURIComponent(pane.sessionId), window.location.href).href;
|
|
17
18
|
if (frame.clayPane ? !livePaneBinding(frame, msg) : frame.src !== expected) return true;
|
|
18
|
-
//
|
|
19
|
+
// Present in the host while browser effects retain the exact source pane binding.
|
|
19
20
|
var binding = frame.clayPane && frame.clayPane.identity().binding, document = frame.contentDocument;
|
|
20
21
|
function current() {
|
|
21
22
|
var now = store.snap();
|
|
@@ -27,6 +28,9 @@ export function handlePaneBrowserMessage(event, host) {
|
|
|
27
28
|
if (binding) return !!frame.clayPane && livePaneBinding(frame, msg) && frame.clayPane.identity().binding === binding;
|
|
28
29
|
return frame.src === expected && !!(now.splitPanes && now.splitPanes.panes.some(function (item) { return String(item.slug) === pane.slug && String(item.sessionId) === String(pane.sessionId); }));
|
|
29
30
|
}
|
|
30
|
-
import('./shared-browser.js').then(function (module) {
|
|
31
|
+
import('./shared-browser.js').then(function (module) {
|
|
32
|
+
if (!current() || binding && !selectBrowserPane(frame, binding)) return;
|
|
33
|
+
module.openSharedBrowserAt(msg.url);
|
|
34
|
+
}).catch(function (error) { showToast(error.message || 'Could not open the browser.', 'warn'); });
|
|
31
35
|
return true;
|
|
32
36
|
}
|