clay-server 5.2.1-beta.2 → 5.3.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/clay-control-presentation-binding.js +5 -3
- package/lib/clay-product-control-tools.js +3 -3
- package/lib/clay-product-control.js +4 -2
- package/lib/clay-screen-controls.js +18 -3
- package/lib/clay-split-view-awareness.js +35 -0
- package/lib/clay-split-view-controls.js +122 -0
- package/lib/clay-split-view-input.js +20 -0
- package/lib/clay-split-view-render-proof.js +22 -0
- package/lib/pane-asset-manifest.js +63 -0
- package/lib/project-connection.js +19 -10
- package/lib/project-session-actions.js +1 -0
- package/lib/project-session-delete.js +2 -2
- package/lib/project-session-folders.js +1 -0
- package/lib/project-sessions.js +6 -1
- package/lib/project-split-view-document.js +33 -0
- package/lib/project-split-view-names.js +67 -0
- package/lib/project-split-view-organization.js +23 -0
- package/lib/project-split-views.js +479 -0
- package/lib/project-worker-conversation.js +158 -0
- package/lib/project-worker-creation-proposal.js +3 -4
- package/lib/project-worker-proposal.js +1 -1
- package/lib/project-worker-removal.js +101 -0
- package/lib/project.js +28 -1
- package/lib/public/app.js +32 -13
- package/lib/public/css/base.css +9 -0
- package/lib/public/css/filebrowser.css +0 -1
- package/lib/public/css/pane-header-controls.css +100 -0
- package/lib/public/css/pane.css +24 -5
- package/lib/public/css/popup-chat.css +123 -0
- package/lib/public/css/right-workbench.css +50 -18
- package/lib/public/css/split-view-layout.css +460 -0
- package/lib/public/css/split-view-worker-activity.css +97 -0
- package/lib/public/css/sticky-notes.css +13 -0
- package/lib/public/index.html +3 -3
- package/lib/public/modules/app-connection.js +4 -1
- package/lib/public/modules/app-messages.js +25 -8
- package/lib/public/modules/chat-render-runtime.js +45 -0
- package/lib/public/modules/clay-control-copy.js +3 -0
- package/lib/public/modules/clay-navigation-render.js +1 -1
- package/lib/public/modules/clay-owner-navigation.js +15 -5
- package/lib/public/modules/clay-split-view-screen.js +74 -0
- package/lib/public/modules/clay-tool-activity.js +5 -0
- package/lib/public/modules/command-palette.js +30 -28
- package/lib/public/modules/contextual-clay-session.js +26 -2
- package/lib/public/modules/contextual-clay.js +5 -2
- package/lib/public/modules/contextual-mate-sessions.js +2 -0
- package/lib/public/modules/generation-stop.js +7 -1
- package/lib/public/modules/knowledge-workbench-entry.js +43 -0
- package/lib/public/modules/markdown.js +11 -0
- package/lib/public/modules/mate-knowledge-workbench.js +2 -7
- package/lib/public/modules/mate-sidebar.js +1 -1
- package/lib/public/modules/palette-clay-conversation.js +87 -0
- package/lib/public/modules/palette-render-helpers.js +25 -0
- package/lib/public/modules/pane-activation.js +46 -7
- package/lib/public/modules/pane-binding.js +12 -2
- package/lib/public/modules/pane-bridge.js +12 -3
- package/lib/public/modules/pane-deferred-bootstrap.js +32 -0
- package/lib/public/modules/pane-feature-assets.js +35 -0
- package/lib/public/modules/pane-search-receipt.js +12 -0
- package/lib/public/modules/permission-control.js +6 -6
- package/lib/public/modules/popup-chat-rendering.js +244 -0
- package/lib/public/modules/project-activation.js +2 -2
- package/lib/public/modules/qrcode.js +12 -1
- package/lib/public/modules/right-workbench.js +68 -0
- package/lib/public/modules/search-hints.js +79 -0
- package/lib/public/modules/session-context-menu.js +35 -2
- package/lib/public/modules/session-folder-context.js +24 -13
- package/lib/public/modules/session-folder-delete.js +18 -1
- package/lib/public/modules/session-folder-layout.js +7 -6
- package/lib/public/modules/session-search-pane-state.js +30 -0
- package/lib/public/modules/session-search.js +53 -13
- package/lib/public/modules/sidebar-mobile.js +3 -3
- package/lib/public/modules/sidebar-projects.js +1 -0
- package/lib/public/modules/sidebar-session-folders-ui.js +3 -3
- package/lib/public/modules/sidebar-sessions.js +57 -24
- package/lib/public/modules/sidebar.js +20 -3
- package/lib/public/modules/split-group-helpers.js +1 -1
- package/lib/public/modules/split-group-restore.js +8 -11
- package/lib/public/modules/split-pair-ui.js +18 -0
- package/lib/public/modules/split-pane-header-state.js +45 -0
- package/lib/public/modules/split-pane-reconciler.js +23 -4
- package/lib/public/modules/split-pane-renderer.js +330 -23
- package/lib/public/modules/split-pane-retention.js +157 -0
- package/lib/public/modules/split-session-boundary.js +21 -0
- package/lib/public/modules/split-view-create-action.js +15 -0
- package/lib/public/modules/split-view-create-menu.js +83 -0
- package/lib/public/modules/split-view-create-request.js +23 -0
- package/lib/public/modules/split-view-layout-client.js +198 -0
- package/lib/public/modules/split-view-layout-icons.js +37 -0
- package/lib/public/modules/split-view-layout-scope.js +38 -0
- package/lib/public/modules/split-view-organization.js +73 -0
- package/lib/public/modules/split-view-presentation-close.js +35 -0
- package/lib/public/modules/split-view-presentation-drag.js +254 -0
- package/lib/public/modules/split-view-presentation-drop.js +57 -0
- package/lib/public/modules/split-view-presentation-lookup.js +44 -0
- package/lib/public/modules/split-view-presentation-renderer.js +494 -0
- package/lib/public/modules/split-view-presentations.js +495 -0
- package/lib/public/modules/split-view-shell-controls.js +28 -0
- package/lib/public/modules/split-view-sidebar-menu.js +42 -0
- package/lib/public/modules/split-view-sidebar-renderer.js +30 -0
- package/lib/public/modules/split-view-singleton.js +21 -0
- package/lib/public/modules/split-view-worker-activity.js +94 -0
- package/lib/public/modules/split-view-worker-controls.js +30 -0
- package/lib/public/modules/split-view-worker-removal.js +137 -0
- package/lib/public/modules/split-view-worker-scroll.js +57 -0
- package/lib/public/modules/split-view-worker-transcript.js +46 -0
- package/lib/public/modules/split-view-workers.js +352 -0
- package/lib/public/modules/split-view.js +61 -22
- package/lib/public/modules/sticky-notes.js +9 -2
- package/lib/public/modules/tools.js +25 -5
- package/lib/public/modules/workbench-layout-preference.js +76 -0
- package/lib/public/pane-assets/app-OJEQXBBS.js +1 -0
- package/lib/public/pane-assets/chunk-4SMIVAB4.js +1 -0
- package/lib/public/pane-assets/chunk-623V5CEO.js +1 -0
- package/lib/public/pane-assets/chunk-6SM2WQJX.js +1 -0
- package/lib/public/pane-assets/chunk-7H36SUZA.js +2 -0
- package/lib/public/pane-assets/chunk-DGOFGEUK.js +1 -0
- package/lib/public/pane-assets/chunk-GML2R5JE.js +167 -0
- package/lib/public/pane-assets/chunk-I57URYSL.js +1 -0
- package/lib/public/pane-assets/chunk-I5P3MWQG.js +1 -0
- package/lib/public/pane-assets/chunk-UVGOPFEX.js +2 -0
- package/lib/public/pane-assets/manifest.json +551 -0
- package/lib/public/pane-assets/style-GN7R6XKV.css +1 -0
- package/lib/public/style.css +5 -1
- package/lib/server-owner-ui.js +6 -2
- package/lib/server-owner-view-observation.js +34 -0
- package/lib/server-palette.js +1 -0
- package/lib/server-pane-bootstrap.js +24 -0
- package/lib/server-settings.js +2 -0
- package/lib/server-static-assets.js +52 -0
- package/lib/server-workbench-layout-settings.js +56 -0
- package/lib/server.js +6 -45
- package/lib/session-activity-state.js +28 -0
- package/lib/session-list-delivery.js +17 -0
- package/lib/session-pair-turn-control.js +1 -6
- package/lib/session-search.js +3 -0
- package/lib/session-split-group-anchors.js +2 -2
- package/lib/session-split-group-roles.js +5 -8
- package/lib/session-split-group-v2-store.js +0 -3
- package/lib/sessions.js +16 -6
- package/lib/split-view-layout.js +132 -0
- package/lib/users-workbench-layout-preferences.js +33 -0
- package/lib/users.js +3 -0
- package/lib/workspace-query-service.js +1 -5
- package/lib/ws-schema.js +15 -0
- package/package.json +6 -3
|
@@ -11,9 +11,11 @@ export function splitPaneIdentity(pane) {
|
|
|
11
11
|
return String(pane && pane.slug || "") + "#" + String(pane && pane.sessionId || "");
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
export function reconcileSplitPanes(host, panes, createPane, updatePane) {
|
|
14
|
+
export function reconcileSplitPanes(host, panes, createPane, updatePane, retention) {
|
|
15
15
|
var desired = Array.isArray(panes) ? panes : [];
|
|
16
|
-
var existing = host.querySelectorAll(".split-pane");
|
|
16
|
+
var existing = host.querySelectorAll(retention ? ".split-pane, .split-pane-cached" : ".split-pane");
|
|
17
|
+
existing = Array.from(existing);
|
|
18
|
+
if (retention) existing.sort(function (a, b) { return retention.age(a) - retention.age(b); });
|
|
17
19
|
var byKey = new Map();
|
|
18
20
|
for (var i = 0; i < existing.length; i++) byKey.set(existing[i].dataset.splitPaneKey, existing[i]);
|
|
19
21
|
var used = new Set();
|
|
@@ -24,20 +26,37 @@ export function reconcileSplitPanes(host, panes, createPane, updatePane) {
|
|
|
24
26
|
if (!paneEl) {
|
|
25
27
|
for (var ci = 0; ci < existing.length; ci++) {
|
|
26
28
|
var candidate = existing[ci], frame = candidate.querySelector('.split-pane-frame');
|
|
27
|
-
if (!used.has(candidate) && frame && frame.dataset.projectSlug === pane.slug && frame.clayPane &&
|
|
29
|
+
if (candidate.parentNode === host && !used.has(candidate) && (!retention || retention.canRetarget(candidate)) && frame && frame.dataset.projectSlug === pane.slug && frame.clayPane &&
|
|
28
30
|
!desired.some(function (item) { return splitPaneIdentity(item) === candidate.dataset.splitPaneKey; })) {
|
|
29
31
|
paneEl = candidate; break;
|
|
30
32
|
}
|
|
31
33
|
}
|
|
32
34
|
}
|
|
35
|
+
if (!paneEl && retention) {
|
|
36
|
+
while (host.querySelectorAll('.split-pane, .split-pane-cached').length >= retention.limit) {
|
|
37
|
+
var victim = existing.find(function (item) { return item.parentNode === host && !used.has(item) &&
|
|
38
|
+
!desired.some(function (model) { return splitPaneIdentity(model) === item.dataset.splitPaneKey; }); });
|
|
39
|
+
if (!victim) break;
|
|
40
|
+
retention.evict(victim);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
33
43
|
if (!paneEl) paneEl = createPane(pane, pi);
|
|
44
|
+
if (retention) retention.restore(paneEl);
|
|
34
45
|
paneEl.dataset.splitPaneKey = key;
|
|
35
46
|
updatePane(paneEl, pane, pi);
|
|
47
|
+
if (retention) retention.remember(paneEl, pane);
|
|
36
48
|
if (paneEl.style) paneEl.style.order = String(pi);
|
|
37
49
|
used.add(paneEl);
|
|
38
50
|
if (!paneEl.parentNode) host.appendChild(paneEl);
|
|
39
51
|
}
|
|
40
52
|
for (var ei = existing.length - 1; ei >= 0; ei--) {
|
|
41
|
-
if (!used.has(existing[ei])
|
|
53
|
+
if (!used.has(existing[ei]) && existing[ei].parentNode === host) {
|
|
54
|
+
if (retention && retention.retain(existing[ei])) retention.park(existing[ei]);
|
|
55
|
+
else if (retention) retention.evict(existing[ei]);
|
|
56
|
+
else {
|
|
57
|
+
if (existing[ei].dispatchEvent) existing[ei].dispatchEvent(new Event('clay-pane-dispose'));
|
|
58
|
+
existing[ei].remove();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
42
61
|
}
|
|
43
62
|
}
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { store } from './store.js';
|
|
2
2
|
import { getWs } from './ws-ref.js';
|
|
3
|
+
import { copyToClipboard } from './utils.js';
|
|
3
4
|
import { getCachedSessions } from './sidebar-sessions.js';
|
|
4
5
|
import { iconHtml } from './icons.js';
|
|
5
6
|
import { formatTokens } from './app-panels.js';
|
|
6
7
|
import { VENDOR_AVATARS, VENDOR_NAMES } from './app-rendering.js';
|
|
7
8
|
import { createPermissionControl, bindPermissionControl, renderPermissionControl } from './permission-control.js';
|
|
8
9
|
import { splitGroupRoles } from './split-group-helpers.js';
|
|
9
|
-
import { paneTarget, livePaneBinding, samePaneTarget } from './pane-binding.js';
|
|
10
|
-
import { syncPairChrome } from './split-pair-ui.js';
|
|
10
|
+
import { paneTarget, livePaneBinding, samePaneTarget, samePaneBinding } from './pane-binding.js';
|
|
11
|
+
import { syncPairChrome, clearPanePairChrome } from './split-pair-ui.js';
|
|
12
|
+
import { renderPaneWorkers } from './split-view-workers.js';
|
|
13
|
+
import { toggleSidebarCollapse } from './sidebar.js';
|
|
14
|
+
import { syncPaneHeaderState } from './split-pane-header-state.js';
|
|
11
15
|
|
|
12
16
|
function sessionById(sessionId) {
|
|
13
17
|
var sessions = getCachedSessions() || [];
|
|
@@ -25,19 +29,219 @@ function headerBindingStamp(frame) {
|
|
|
25
29
|
live && live.binding && live.binding.requestId, live && live.binding && live.binding.generation]);
|
|
26
30
|
}
|
|
27
31
|
|
|
32
|
+
function capturePaneSearchReceipt(paneEl, frame, binding) {
|
|
33
|
+
var live = frame.clayPane && frame.clayPane.identity(), state = store.snap();
|
|
34
|
+
if (!live || !live.ready || !binding || !samePaneBinding(live.binding, binding) || !livePaneBinding(frame, { paneBinding: binding }) ||
|
|
35
|
+
live.sessionId !== Number(frame.dataset.sessionId) || binding.sessionOriginId !== frame.dataset.sessionOriginId ||
|
|
36
|
+
Number(paneEl.dataset.sessionId) !== live.sessionId || paneEl.hidden || paneEl.inert || frame.closest('.split-pane-cached') ||
|
|
37
|
+
state.paneSuspended || !state.connected || !getWs()) return null;
|
|
38
|
+
return { binding: binding, source: frame.contentWindow, document: frame.contentDocument, socket: getWs(),
|
|
39
|
+
projectSlug: state.currentSlug, ownerId: state.myUserId, sessionId: live.sessionId, sessionOriginId: binding.sessionOriginId };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function paneSearchReceiptCurrent(paneEl, frame, receipt) {
|
|
43
|
+
if (!receipt || !paneEl.isConnected || paneEl.hidden || paneEl.inert || frame.closest('.split-pane-cached') ||
|
|
44
|
+
frame.contentWindow !== receipt.source || frame.contentDocument !== receipt.document || getWs() !== receipt.socket) return false;
|
|
45
|
+
var state = store.snap(), live = frame.clayPane && frame.clayPane.identity();
|
|
46
|
+
return state.connected && !state.paneSuspended && state.currentSlug === receipt.projectSlug && state.myUserId === receipt.ownerId &&
|
|
47
|
+
live && live.ready && live.sessionId === receipt.sessionId && live.binding.sessionOriginId === receipt.sessionOriginId &&
|
|
48
|
+
samePaneBinding(live.binding, receipt.binding) && livePaneBinding(frame, { paneBinding: receipt.binding }) &&
|
|
49
|
+
Number(paneEl.dataset.sessionId) === receipt.sessionId && Number(frame.dataset.sessionId) === receipt.sessionId &&
|
|
50
|
+
frame.dataset.sessionOriginId === receipt.sessionOriginId;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function sendPaneSearchCommand(paneEl, frame, receipt, action, query) {
|
|
54
|
+
if (!paneSearchReceiptCurrent(paneEl, frame, receipt) || !['open', 'query', 'next', 'previous', 'close'].includes(action)) return false;
|
|
55
|
+
frame.contentWindow.postMessage({ type: "clay-pane-search-command", paneBinding: receipt.binding, action: action, query: query }, window.location.origin);
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
var paneSearchDismissalInstalled = false;
|
|
60
|
+
|
|
61
|
+
function createPaneSearchPopover(paneEl, frame, searchButton) {
|
|
62
|
+
var popover = document.createElement("div");
|
|
63
|
+
popover.className = "split-pane-search-popover";
|
|
64
|
+
popover.hidden = true;
|
|
65
|
+
popover.setAttribute("role", "search");
|
|
66
|
+
var input = document.createElement("input");
|
|
67
|
+
input.type = "search"; input.className = "split-pane-search-input";
|
|
68
|
+
input.placeholder = "Search this session"; input.autocomplete = "off"; input.spellcheck = false;
|
|
69
|
+
input.setAttribute("aria-label", "Search this session");
|
|
70
|
+
var count = document.createElement("span"); count.className = "split-pane-search-count"; count.setAttribute("aria-live", "polite");
|
|
71
|
+
var paneHeader = paneEl.querySelector(".split-pane-header");
|
|
72
|
+
var receipt = null;
|
|
73
|
+
var timer = null;
|
|
74
|
+
var disposed = false;
|
|
75
|
+
var actionGesture = null;
|
|
76
|
+
var headerObserver = null;
|
|
77
|
+
var unsubscribe = null;
|
|
78
|
+
function setSearchTop() {
|
|
79
|
+
if (!popover.hidden && paneHeader && paneEl.getBoundingClientRect && paneHeader.getBoundingClientRect && paneEl.style && paneEl.style.setProperty) {
|
|
80
|
+
var paneRect = paneEl.getBoundingClientRect(), headerRect = paneHeader.getBoundingClientRect();
|
|
81
|
+
paneEl.style.setProperty('--split-pane-search-top', Math.max(0, headerRect.bottom - paneRect.top) + 'px');
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function actionButton(label, action, icon) {
|
|
85
|
+
var button = document.createElement("button"); button.type = "button";
|
|
86
|
+
button.className = "split-pane-search-action"; button.title = label; button.setAttribute("aria-label", label);
|
|
87
|
+
button.innerHTML = iconHtml(icon);
|
|
88
|
+
function arm(event) { if (event.type === 'pointerdown' || event.key === 'Enter' || event.key === ' ') actionGesture = { receipt: receipt }; }
|
|
89
|
+
button.addEventListener('pointerdown', arm);
|
|
90
|
+
button.addEventListener('keydown', arm);
|
|
91
|
+
button.addEventListener("click", function () {
|
|
92
|
+
var gesture = actionGesture; actionGesture = null;
|
|
93
|
+
var captured = gesture ? gesture.receipt : receipt;
|
|
94
|
+
if (!disposed && captured === receipt && sendPaneSearchCommand(paneEl, frame, captured, action)) input.focus();
|
|
95
|
+
});
|
|
96
|
+
return button;
|
|
97
|
+
}
|
|
98
|
+
var previous = actionButton("Previous match", "previous", "chevron-up");
|
|
99
|
+
var next = actionButton("Next match", "next", "chevron-down");
|
|
100
|
+
var close = document.createElement("button"); close.type = "button"; close.className = "split-pane-search-action";
|
|
101
|
+
close.title = "Close search"; close.setAttribute("aria-label", "Close search"); close.innerHTML = iconHtml("x");
|
|
102
|
+
input.addEventListener("input", function () {
|
|
103
|
+
clearTimeout(timer);
|
|
104
|
+
var openedReceipt = receipt;
|
|
105
|
+
timer = setTimeout(function () {
|
|
106
|
+
if (!disposed && openedReceipt === receipt) sendPaneSearchCommand(paneEl, frame, openedReceipt, "query", input.value);
|
|
107
|
+
}, 180);
|
|
108
|
+
});
|
|
109
|
+
input.addEventListener("keydown", function (event) {
|
|
110
|
+
if (event.key === "Enter") { event.preventDefault(); sendPaneSearchCommand(paneEl, frame, receipt, event.shiftKey ? "previous" : "next"); }
|
|
111
|
+
if (event.key === "Escape") { event.preventDefault(); closeSearch(); }
|
|
112
|
+
});
|
|
113
|
+
popover.addEventListener("click", function (event) { event.stopPropagation(); });
|
|
114
|
+
function closeSearch(restoreFocus, sendClose, expectedReceipt) {
|
|
115
|
+
if (disposed) return;
|
|
116
|
+
if (expectedReceipt && expectedReceipt !== receipt) return;
|
|
117
|
+
var closingReceipt = receipt;
|
|
118
|
+
clearTimeout(timer);
|
|
119
|
+
if (sendClose !== false) sendPaneSearchCommand(paneEl, frame, closingReceipt, "close");
|
|
120
|
+
receipt = null;
|
|
121
|
+
popover.hidden = true; searchButton.setAttribute("aria-expanded", "false");
|
|
122
|
+
if (restoreFocus !== false) searchButton.focus();
|
|
123
|
+
}
|
|
124
|
+
function armClose(event) { if (event.type === 'pointerdown' || event.key === 'Enter' || event.key === ' ') actionGesture = { receipt: receipt }; }
|
|
125
|
+
close.addEventListener('pointerdown', armClose);
|
|
126
|
+
close.addEventListener('keydown', armClose);
|
|
127
|
+
close.addEventListener("click", function () {
|
|
128
|
+
var gesture = actionGesture; actionGesture = null;
|
|
129
|
+
if (!disposed && (!gesture || gesture.receipt === receipt)) closeSearch();
|
|
130
|
+
});
|
|
131
|
+
popover.closePaneSearch = closeSearch;
|
|
132
|
+
popover.getPaneSearchReceipt = function () { return receipt; };
|
|
133
|
+
popover.openPaneSearch = function (binding) {
|
|
134
|
+
if (disposed) return false;
|
|
135
|
+
var captured = capturePaneSearchReceipt(paneEl, frame, binding);
|
|
136
|
+
if (!captured) return false;
|
|
137
|
+
receipt = captured;
|
|
138
|
+
popover.hidden = false; searchButton.setAttribute("aria-expanded", "true");
|
|
139
|
+
setSearchTop(); sendPaneSearchCommand(paneEl, frame, receipt, "open", input.value); input.focus(); input.select();
|
|
140
|
+
return true;
|
|
141
|
+
};
|
|
142
|
+
if (!paneSearchDismissalInstalled) {
|
|
143
|
+
paneSearchDismissalInstalled = true;
|
|
144
|
+
document.addEventListener("pointerdown", function (event) {
|
|
145
|
+
var openPopovers = document.querySelectorAll(".split-pane-search-popover:not([hidden])");
|
|
146
|
+
for (var i = 0; i < openPopovers.length; i++) {
|
|
147
|
+
var openPopover = openPopovers[i];
|
|
148
|
+
var owner = openPopover.closest(".split-pane");
|
|
149
|
+
var trigger = owner && owner.querySelector(".split-pane-search");
|
|
150
|
+
if (!openPopover.contains(event.target) && event.target !== trigger && openPopover.closePaneSearch) openPopover.closePaneSearch(false);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
searchButton.setAttribute("aria-expanded", "false");
|
|
155
|
+
searchButton.addEventListener("click", function (event) {
|
|
156
|
+
event.stopPropagation();
|
|
157
|
+
if (!syncPaneHeaderState(paneEl)) return;
|
|
158
|
+
var live = frame.clayPane && frame.clayPane.identity();
|
|
159
|
+
if (!live || !live.ready || !livePaneBinding(frame) || live.sessionId !== Number(frame.dataset.sessionId) ||
|
|
160
|
+
live.binding.sessionOriginId !== frame.dataset.sessionOriginId || Number(paneEl.dataset.sessionId) !== live.sessionId) return;
|
|
161
|
+
if (!popover.hidden) { closeSearch(); return; }
|
|
162
|
+
popover.openPaneSearch(live.binding);
|
|
163
|
+
});
|
|
164
|
+
function resetForBindingChange() { closeSearch(false, false); input.value = ""; count.textContent = ""; syncPaneHeaderState(paneEl); }
|
|
165
|
+
function onStoreChange() {
|
|
166
|
+
if (receipt && !paneSearchReceiptCurrent(paneEl, frame, receipt)) resetForBindingChange();
|
|
167
|
+
else syncPaneHeaderState(paneEl);
|
|
168
|
+
}
|
|
169
|
+
function dispose() {
|
|
170
|
+
if (disposed) return;
|
|
171
|
+
closeSearch(false, false);
|
|
172
|
+
disposed = true; clearTimeout(timer); timer = null; actionGesture = null;
|
|
173
|
+
frame.removeEventListener("clay-pane-retarget", resetForBindingChange);
|
|
174
|
+
if (paneHeader) paneHeader.removeEventListener("clay-pane-retarget", resetForBindingChange);
|
|
175
|
+
frame.removeEventListener("clay-pane-activation-failed", resetForBindingChange);
|
|
176
|
+
frame.removeEventListener("clay-pane-suspend", resetForBindingChange);
|
|
177
|
+
if (unsubscribe) { unsubscribe(); unsubscribe = null; }
|
|
178
|
+
window.removeEventListener("resize", setSearchTop);
|
|
179
|
+
if (headerObserver) { headerObserver.disconnect(); headerObserver = null; }
|
|
180
|
+
paneEl.removeEventListener('clay-pane-dispose', dispose);
|
|
181
|
+
}
|
|
182
|
+
paneEl.addEventListener('clay-pane-dispose', dispose);
|
|
183
|
+
paneEl.disposePaneSearchPopover = dispose;
|
|
184
|
+
try {
|
|
185
|
+
frame.addEventListener("clay-pane-retarget", resetForBindingChange);
|
|
186
|
+
if (paneHeader) paneHeader.addEventListener("clay-pane-retarget", resetForBindingChange);
|
|
187
|
+
frame.addEventListener("clay-pane-activation-failed", resetForBindingChange);
|
|
188
|
+
frame.addEventListener("clay-pane-suspend", resetForBindingChange);
|
|
189
|
+
unsubscribe = store.subscribe(onStoreChange);
|
|
190
|
+
window.addEventListener("resize", setSearchTop);
|
|
191
|
+
if (typeof ResizeObserver === 'function') {
|
|
192
|
+
headerObserver = new ResizeObserver(setSearchTop);
|
|
193
|
+
if (paneHeader) headerObserver.observe(paneHeader);
|
|
194
|
+
}
|
|
195
|
+
popover.appendChild(input); popover.appendChild(count); popover.appendChild(previous); popover.appendChild(next); popover.appendChild(close);
|
|
196
|
+
paneEl.appendChild(popover);
|
|
197
|
+
return { popover: popover, input: input, count: count, close: closeSearch, button: searchButton };
|
|
198
|
+
} catch (error) {
|
|
199
|
+
dispose();
|
|
200
|
+
throw error;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export function handlePaneSearchMessage(event, host) {
|
|
205
|
+
var frames = host ? host.querySelectorAll(".split-pane-frame") : [];
|
|
206
|
+
for (var i = 0; i < frames.length; i++) {
|
|
207
|
+
var frame = frames[i], live = frame.clayPane && frame.clayPane.identity();
|
|
208
|
+
if (frame.contentWindow !== event.source || !live || !livePaneBinding(frame, event.data) || live.sessionId !== Number(frame.dataset.sessionId)) continue;
|
|
209
|
+
var paneEl = frame.closest(".split-pane"), popover = paneEl && paneEl.querySelector(".split-pane-search-popover");
|
|
210
|
+
if (!popover) return true;
|
|
211
|
+
if (event.data.type === "clay-pane-search-status") {
|
|
212
|
+
var count = popover.querySelector(".split-pane-search-count");
|
|
213
|
+
var input = popover.querySelector(".split-pane-search-input");
|
|
214
|
+
var receipt = popover.getPaneSearchReceipt && popover.getPaneSearchReceipt();
|
|
215
|
+
if (receipt && samePaneBinding(receipt.binding, live.binding) && paneSearchReceiptCurrent(paneEl, frame, receipt)) {
|
|
216
|
+
if (event.data.open === false) popover.closePaneSearch(true, false, receipt);
|
|
217
|
+
else if (!popover.hidden && event.data.query === input.value.trim()) count.textContent = event.data.status || "";
|
|
218
|
+
}
|
|
219
|
+
} else if (event.data.type === "clay-pane-search-open" && popover.hidden) {
|
|
220
|
+
var input = popover.querySelector('.split-pane-search-input');
|
|
221
|
+
popover.openPaneSearch(live.binding);
|
|
222
|
+
}
|
|
223
|
+
return true;
|
|
224
|
+
}
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
|
|
28
228
|
function startPaneRename(header, titleEl, pane) {
|
|
29
229
|
if (header.querySelector(".split-pane-rename-input")) return;
|
|
230
|
+
var section = header.parentNode, frame = section.querySelector('.split-pane-frame');
|
|
231
|
+
var initial = frame && frame.clayPane && frame.clayPane.identity();
|
|
232
|
+
if (!initial || !initial.ready || !livePaneBinding(frame) || initial.sessionId !== pane.sessionId ||
|
|
233
|
+
initial.binding.sessionOriginId !== frame.dataset.sessionOriginId) return;
|
|
30
234
|
var input = document.createElement("input");
|
|
31
235
|
input.type = "text"; input.className = "split-pane-rename-input"; input.value = pane.title;
|
|
32
236
|
titleEl.style.display = "none"; header.insertBefore(input, titleEl); input.focus(); input.select();
|
|
33
237
|
var done = false;
|
|
34
|
-
var
|
|
35
|
-
var origin = frame.dataset.sessionOriginId, binding = frame.clayPane && frame.clayPane.identity().binding, socket = getWs();
|
|
238
|
+
var origin = frame.dataset.sessionOriginId, binding = initial.binding, socket = getWs();
|
|
36
239
|
function current() {
|
|
37
240
|
var live = frame.clayPane && frame.clayPane.identity();
|
|
38
241
|
return header.isConnected && !header.inert && socket === getWs() && store.get('connected') &&
|
|
39
242
|
frame.dataset.sessionId === String(pane.sessionId) && frame.dataset.sessionOriginId === origin && !frame.dataset.requestedSessionId &&
|
|
40
|
-
|
|
243
|
+
!!live && live.ready && live.sessionId === pane.sessionId && live.binding.sessionOriginId === origin &&
|
|
244
|
+
livePaneBinding(frame) && samePaneBinding(live.binding, binding);
|
|
41
245
|
}
|
|
42
246
|
function finish(commit) {
|
|
43
247
|
if (done) return;
|
|
@@ -86,11 +290,11 @@ export function updatePaneFullAccessButton(button, session) {
|
|
|
86
290
|
export function createSplitPane(pane, closePane) {
|
|
87
291
|
var paneEl = document.createElement("section"); paneEl.className = "split-pane";
|
|
88
292
|
var header = document.createElement("header"); header.className = "split-pane-header"; header.title = pane.title;
|
|
89
|
-
var session = sessionById(pane.sessionId); var vendor = session && session.vendor || "
|
|
90
|
-
var vendorIcon = document.createElement("img"); vendorIcon.className = "split-pane-vendor";
|
|
91
|
-
vendorIcon.src = VENDOR_AVATARS[vendor]
|
|
293
|
+
var session = sessionById(pane.sessionId); var vendor = session && session.vendor || "unknown";
|
|
294
|
+
var vendorIcon = document.createElement("img"); vendorIcon.className = "split-pane-vendor"; vendorIcon.hidden = !VENDOR_AVATARS[vendor];
|
|
295
|
+
if (!vendorIcon.hidden) vendorIcon.src = VENDOR_AVATARS[vendor]; vendorIcon.alt = ""; vendorIcon.title = VENDOR_NAMES[vendor] || vendor; header.appendChild(vendorIcon);
|
|
92
296
|
var title = document.createElement("span"); title.className = "split-pane-title"; title.textContent = pane.title; title.title = "Rename session";
|
|
93
|
-
title.addEventListener("click", function () { var current = sessionById(Number(paneEl.dataset.sessionId)); if (current) startPaneRename(header, title, { sessionId: current.id, title: current.title }); }); header.appendChild(title);
|
|
297
|
+
title.addEventListener("click", function () { if (title.getAttribute('aria-disabled') === 'true' || !syncPaneHeaderState(paneEl)) return; var current = sessionById(Number(paneEl.dataset.sessionId)); if (current) startPaneRename(header, title, { sessionId: current.id, title: current.title }); }); header.appendChild(title);
|
|
94
298
|
var frame = document.createElement("iframe"); frame.className = "split-pane-frame"; frame.dataset.projectSlug = pane.slug;
|
|
95
299
|
frame.dataset.sessionId = String(pane.sessionId); frame.src = paneUrl(pane); frame.title = pane.title;
|
|
96
300
|
frame.dataset.sessionOriginId = session && session.sessionOriginId || '';
|
|
@@ -109,12 +313,38 @@ export function createSplitPane(pane, closePane) {
|
|
|
109
313
|
});
|
|
110
314
|
var ctxChip = document.createElement("button"); ctxChip.type = "button"; ctxChip.className = "split-pane-context"; ctxChip.title = "Context usage";
|
|
111
315
|
ctxChip.innerHTML = '<span class="split-pane-context-bar"><span class="split-pane-context-fill"></span></span><span class="split-pane-context-label"></span>';
|
|
112
|
-
ctxChip.addEventListener("click", function () { if (frame.contentWindow &&
|
|
316
|
+
ctxChip.addEventListener("click", function () { if (syncPaneHeaderState(paneEl) && frame.contentWindow && frame.clayPane && livePaneBinding(frame)) frame.contentWindow.postMessage({ type: "clay-pane-toggle-context", paneBinding: frame.clayPane.identity().binding }, window.location.origin); }); header.appendChild(ctxChip);
|
|
113
317
|
var fullAccess = createPermissionControl("split-pane-full-access hidden", "Driver session permission mode");
|
|
114
318
|
updatePaneFullAccessButton(fullAccess, session); bindPermissionControl(fullAccess, function () { return permissionState(sessionById(Number(paneEl.dataset.sessionId))); }); header.appendChild(fullAccess); header.insertBefore(fullAccess, ctxChip);
|
|
115
319
|
var close = document.createElement("button"); close.type = "button"; close.className = "split-pane-close"; close.title = "Close pane"; close.setAttribute("aria-label", "Close pane"); close.innerHTML = iconHtml("x");
|
|
116
|
-
|
|
320
|
+
if (store.get('projectSplitViewSingletonOrigin') === (session && session.sessionOriginId)) {
|
|
321
|
+
close.hidden = true; close.title = "The only pane cannot be closed"; close.setAttribute("aria-label", "The only pane cannot be closed");
|
|
322
|
+
}
|
|
323
|
+
close.dataset.sessionId = String(pane.sessionId); close.addEventListener("click", function () { if (syncPaneHeaderState(paneEl)) closePane(Number(this.dataset.sessionId)); }); header.appendChild(close);
|
|
324
|
+
var info = document.createElement("button"); info.type = "button"; info.className = "split-pane-info"; info.setAttribute("aria-label", "Session information"); info.title = "Session information"; info.innerHTML = iconHtml("info");
|
|
325
|
+
info.addEventListener("click", function (event) { event.stopPropagation(); if (syncPaneHeaderState(paneEl)) togglePaneInfo(info, frame); }); header.appendChild(info);
|
|
326
|
+
var sidebarButton = document.createElement("button"); sidebarButton.type = "button"; sidebarButton.className = "split-pane-sidebar";
|
|
327
|
+
var sidebarExpanded = !document.getElementById("layout").classList.contains("sidebar-collapsed");
|
|
328
|
+
sidebarButton.setAttribute("aria-label", sidebarExpanded ? "Collapse sidebar" : "Open sidebar");
|
|
329
|
+
sidebarButton.setAttribute("aria-expanded", sidebarExpanded ? "true" : "false");
|
|
330
|
+
sidebarButton.title = sidebarExpanded ? "Collapse sidebar" : "Open sidebar"; sidebarButton.innerHTML = iconHtml("panel-left");
|
|
331
|
+
sidebarButton.addEventListener("click", function (event) {
|
|
332
|
+
event.stopPropagation();
|
|
333
|
+
if (!syncPaneHeaderState(paneEl)) return;
|
|
334
|
+
var live = frame.clayPane && frame.clayPane.identity();
|
|
335
|
+
var activePane = paneEl.dataset.active === "true" || live && store.get('projectSplitViewSingletonOrigin') === live.binding.sessionOriginId;
|
|
336
|
+
if (!live || !live.ready || !livePaneBinding(frame) || live.sessionId !== Number(frame.dataset.sessionId) ||
|
|
337
|
+
live.binding.sessionOriginId !== frame.dataset.sessionOriginId || !activePane) return;
|
|
338
|
+
toggleSidebarCollapse();
|
|
339
|
+
var expanded = !document.getElementById("layout").classList.contains("sidebar-collapsed");
|
|
340
|
+
sidebarButton.setAttribute("aria-expanded", expanded ? "true" : "false");
|
|
341
|
+
sidebarButton.setAttribute("aria-label", expanded ? "Collapse sidebar" : "Open sidebar");
|
|
342
|
+
sidebarButton.title = expanded ? "Collapse sidebar" : "Open sidebar";
|
|
343
|
+
}); header.appendChild(sidebarButton);
|
|
344
|
+
var search = document.createElement("button"); search.type = "button"; search.className = "split-pane-search"; search.setAttribute("aria-label", "Search this session"); search.title = "Search this session"; search.innerHTML = iconHtml("search");
|
|
345
|
+
header.insertBefore(search, close);
|
|
117
346
|
frame.addEventListener('clay-pane-ready', function () {
|
|
347
|
+
if (paneEl.classList.contains('split-pane-cached')) return;
|
|
118
348
|
var id = Number(frame.dataset.requestedSessionId || frame.dataset.sessionId), current = sessionById(id);
|
|
119
349
|
var live = frame.clayPane && frame.clayPane.identity(), target = paneTarget(store.snap(), getCachedSessions(), id);
|
|
120
350
|
if (!current || !live || !live.ready || !samePaneTarget(target, live.binding) || live.sessionId !== id) return;
|
|
@@ -124,24 +354,74 @@ export function createSplitPane(pane, closePane) {
|
|
|
124
354
|
syncPairChrome(paneEl.parentNode, store.get('splitPanes'));
|
|
125
355
|
});
|
|
126
356
|
frame.addEventListener('clay-pane-activation-failed', function () {
|
|
357
|
+
if (paneEl.classList.contains('split-pane-cached')) return;
|
|
358
|
+
syncPaneHeaderState(paneEl);
|
|
127
359
|
var id = Number(frame.dataset.requestedSessionId || frame.dataset.sessionId);
|
|
128
360
|
var fallbackTarget = paneTarget(store.snap(), getCachedSessions(), id);
|
|
129
|
-
if (!fallbackTarget) { header.inert = true; return; }
|
|
361
|
+
if (!fallbackTarget) { header.inert = true; syncPaneHeaderState(paneEl); return; }
|
|
130
362
|
frame.dataset.sessionOriginId = fallbackTarget.sessionOriginId;
|
|
131
363
|
frame.src = paneUrl({ slug: frame.dataset.projectSlug, sessionId: id });
|
|
132
364
|
frame.dataset.sessionId = String(id); delete frame.dataset.requestedSessionId;
|
|
365
|
+
syncPaneHeaderState(paneEl);
|
|
133
366
|
});
|
|
134
|
-
paneEl.appendChild(header);
|
|
367
|
+
paneEl.appendChild(header);
|
|
368
|
+
createPaneSearchPopover(paneEl, frame, search);
|
|
369
|
+
var runtime = document.createElement("div"); runtime.className = "split-view-runtime";
|
|
370
|
+
vendorIcon.classList.add("split-view-runtime-icon"); runtime.appendChild(vendorIcon);
|
|
371
|
+
var runtimeModel = document.createElement("span"); runtimeModel.className = "split-view-model"; runtime.appendChild(runtimeModel);
|
|
372
|
+
header.insertBefore(runtime, title); header.appendChild(close); paneEl.appendChild(frame);
|
|
373
|
+
syncPaneHeaderState(paneEl);
|
|
374
|
+
return paneEl;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
function togglePaneInfo(anchor, frame) {
|
|
378
|
+
var existing = document.getElementById("split-pane-info-popover");
|
|
379
|
+
if (existing) { existing.remove(); if (existing.dataset.origin === frame.dataset.sessionOriginId) return; }
|
|
380
|
+
var live = frame.clayPane && frame.clayPane.identity();
|
|
381
|
+
if (!live || !live.ready || !livePaneBinding(frame) || live.binding.sessionOriginId !== frame.dataset.sessionOriginId || live.sessionId !== Number(frame.dataset.sessionId)) return;
|
|
382
|
+
var session = sessionById(live.sessionId);
|
|
383
|
+
if (!session || session.sessionOriginId !== live.binding.sessionOriginId) return;
|
|
384
|
+
var binding = live.binding;
|
|
385
|
+
function current() {
|
|
386
|
+
var currentLive = frame.clayPane && frame.clayPane.identity();
|
|
387
|
+
return anchor.isConnected && !anchor.closest('.split-pane-header').inert && frame.dataset.sessionId === String(session.id) &&
|
|
388
|
+
frame.dataset.sessionOriginId === session.sessionOriginId && !frame.dataset.requestedSessionId && currentLive &&
|
|
389
|
+
currentLive.ready && currentLive.sessionId === session.id && samePaneBinding(currentLive.binding, binding) && livePaneBinding(frame);
|
|
390
|
+
}
|
|
391
|
+
var pop = document.createElement("div"); pop.id = "split-pane-info-popover"; pop.className = "session-info-popover"; pop.dataset.origin = session.sessionOriginId;
|
|
392
|
+
var values = [["Local ID", session.id]];
|
|
393
|
+
if (session.cliSessionId) values.push(["Session ID", session.cliSessionId]);
|
|
394
|
+
var vendor = (store.get("vendorInfo") || {})[session.vendor || "claude"] || {};
|
|
395
|
+
if (session.cliSessionId && vendor.terminalResumeCommand) values.push(["Resume", vendor.terminalResumeCommand + " " + session.cliSessionId]);
|
|
396
|
+
values.forEach(function (entry) {
|
|
397
|
+
var row = document.createElement("div"); row.className = "info-row";
|
|
398
|
+
var label = document.createElement("span"); label.className = "info-label"; label.textContent = entry[0];
|
|
399
|
+
var value = document.createElement("span"); value.className = "info-value"; value.textContent = String(entry[1]);
|
|
400
|
+
var copy = document.createElement("button"); copy.type = "button"; copy.className = "info-copy-btn"; copy.title = "Copy " + entry[0]; copy.setAttribute("aria-label", "Copy " + entry[0]); copy.innerHTML = iconHtml("copy");
|
|
401
|
+
copy.addEventListener("click", function () { if (!current()) { pop.remove(); return; } copyToClipboard(String(entry[1])).then(function () { if (pop.isConnected && current()) copy.innerHTML = iconHtml("check"); }); });
|
|
402
|
+
row.append(label, value, copy); pop.appendChild(row);
|
|
403
|
+
});
|
|
404
|
+
document.body.appendChild(pop);
|
|
405
|
+
var rect = anchor.getBoundingClientRect(); pop.style.top = (rect.bottom + 6) + "px"; pop.style.left = Math.max(8, Math.min(rect.left, window.innerWidth - pop.offsetWidth - 8)) + "px";
|
|
406
|
+
function dismiss(event) { if (event.type === "keydown" && event.key !== "Escape") return; if (event.type === "click" && (pop.contains(event.target) || anchor.contains(event.target))) return; pop.remove(); document.removeEventListener("click", dismiss, true); document.removeEventListener("keydown", dismiss, true); frame.removeEventListener('clay-pane-retarget', dismiss); frame.removeEventListener('clay-pane-ready', dismiss); if (event.type === "keydown") anchor.focus(); }
|
|
407
|
+
document.addEventListener("click", dismiss, true); document.addEventListener("keydown", dismiss, true);
|
|
408
|
+
frame.addEventListener('clay-pane-retarget', dismiss); frame.addEventListener('clay-pane-ready', dismiss);
|
|
135
409
|
}
|
|
136
410
|
|
|
137
411
|
export function updateSplitPaneMetadata(paneEl, pane) {
|
|
412
|
+
clearPanePairChrome(paneEl);
|
|
138
413
|
var session = sessionById(pane.sessionId); var header = paneEl.querySelector(".split-pane-header");
|
|
139
414
|
var title = paneEl.querySelector(".split-pane-title"); var frame = paneEl.querySelector(".split-pane-frame"); var vendor = paneEl.querySelector(".split-pane-vendor");
|
|
140
415
|
var live = frame && frame.clayPane && frame.clayPane.identity();
|
|
141
416
|
var retarget = frame && (Number(frame.dataset.sessionId) !== pane.sessionId || frame.dataset.sessionOriginId !== (session && session.sessionOriginId || '') || frame.clayPane && (!live || !live.ready));
|
|
417
|
+
if (retarget && frame && frame.clayPane) {
|
|
418
|
+
// Invalidate the old ready binding before header sync exposes any action.
|
|
419
|
+
frame.dataset.requestedSessionId = String(pane.sessionId);
|
|
420
|
+
}
|
|
142
421
|
if (retarget && header) {
|
|
143
422
|
header.dispatchEvent(new Event('clay-pane-retarget'));
|
|
144
423
|
header.inert = true;
|
|
424
|
+
syncPaneHeaderState(paneEl);
|
|
145
425
|
header.title = 'Loading conversation';
|
|
146
426
|
if (title) { title.style.display = ''; title.textContent = 'Loading conversation'; }
|
|
147
427
|
if (vendor) vendor.hidden = true;
|
|
@@ -151,24 +431,51 @@ export function updateSplitPaneMetadata(paneEl, pane) {
|
|
|
151
431
|
}
|
|
152
432
|
if (frame && frame.clayPane && retarget) {
|
|
153
433
|
var target = paneTarget(store.snap(), getCachedSessions(), pane.sessionId);
|
|
154
|
-
if (target && frame.clayPane.source === frame.contentWindow && frame.clayPane.document === frame.contentDocument
|
|
155
|
-
frame.
|
|
156
|
-
|
|
157
|
-
|
|
434
|
+
if (target && frame.clayPane.source === frame.contentWindow && frame.clayPane.document === frame.contentDocument) {
|
|
435
|
+
if (frame.clayPane.activate(pane.sessionId, false, target)) {
|
|
436
|
+
if (header) header.inert = true;
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
// A same-target document can expose its controller before its socket and
|
|
440
|
+
// identity are ready. Its bootstrap retries activation; reloading here
|
|
441
|
+
// restarts that bootstrap on every metadata update.
|
|
442
|
+
if ((!live || !live.ready) && Number(frame.dataset.sessionId) === pane.sessionId &&
|
|
443
|
+
frame.dataset.projectSlug === pane.slug && frame.dataset.sessionOriginId === target.sessionOriginId) return;
|
|
158
444
|
}
|
|
445
|
+
delete frame.dataset.requestedSessionId;
|
|
159
446
|
frame.src = paneUrl(pane);
|
|
160
447
|
frame.dataset.sessionId = String(pane.sessionId); frame.dataset.projectSlug = pane.slug;
|
|
161
448
|
frame.dataset.sessionOriginId = session && session.sessionOriginId || '';
|
|
162
449
|
}
|
|
163
|
-
if (header) header.inert = false;
|
|
164
450
|
paneEl.dataset.sessionId = String(pane.sessionId); paneEl.dataset.projectSlug = pane.slug;
|
|
451
|
+
paneEl.dataset.sessionOrigin = session && session.sessionOriginId || "";
|
|
165
452
|
if (header) header.title = pane.title; if (title && title.style.display !== "none") title.textContent = pane.title; if (frame) frame.title = pane.title;
|
|
166
|
-
|
|
453
|
+
var sidebarButton = paneEl.querySelector('.split-pane-sidebar');
|
|
454
|
+
if (sidebarButton) sidebarButton.hidden = store.get('projectSplitViewSingletonOrigin') !== (session && session.sessionOriginId) && paneEl.dataset.active !== 'true';
|
|
455
|
+
if (vendor) { var vendorName = session && session.vendor || "unknown"; vendor.hidden = !VENDOR_AVATARS[vendorName]; if (!vendor.hidden) vendor.src = VENDOR_AVATARS[vendorName]; vendor.title = VENDOR_NAMES[vendorName] || vendorName; }
|
|
456
|
+
var runtime = paneEl.querySelector('.split-view-runtime');
|
|
457
|
+
var runtimeName = session && session.vendor || "unknown", runtimeModelName = session && typeof session.model === "string" && session.model.trim() || "Model unavailable";
|
|
458
|
+
var runtimeIcon = runtime.querySelector('.split-view-runtime-icon'), runtimeModel = runtime.querySelector('.split-view-model');
|
|
459
|
+
if (runtimeIcon) { runtimeIcon.hidden = !VENDOR_AVATARS[runtimeName]; if (!runtimeIcon.hidden) runtimeIcon.src = VENDOR_AVATARS[runtimeName]; runtimeIcon.title = VENDOR_NAMES[runtimeName] || runtimeName; runtimeIcon.alt = ""; }
|
|
460
|
+
if (runtimeModel) { runtimeModel.textContent = runtimeModelName; runtimeModel.title = (VENDOR_NAMES[runtimeName] || runtimeName) + " · " + runtimeModelName; }
|
|
461
|
+
runtime.setAttribute("aria-label", (VENDOR_NAMES[runtimeName] || runtimeName) + " · " + runtimeModelName);
|
|
462
|
+
renderPaneWorkers(paneEl, session);
|
|
167
463
|
updatePaneFullAccessButton(paneEl.querySelector('.split-pane-full-access'), session);
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
464
|
+
syncPaneHeaderState(paneEl);
|
|
465
|
+
updateSplitPaneCloseVisibility(paneEl, pane.sessionId);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
export function updateSplitPaneCloseVisibility(paneEl, sessionId) {
|
|
469
|
+
var close = paneEl && paneEl.querySelector('.split-pane-close');
|
|
470
|
+
if (!close) return;
|
|
471
|
+
var paneHost = paneEl.parentNode;
|
|
472
|
+
var singletonOnly = !!paneHost && paneHost.id === 'split-host' && paneHost.dataset && paneHost.dataset.singlePane === 'true' &&
|
|
473
|
+
paneHost.querySelectorAll(':scope > .split-pane').length === 1;
|
|
474
|
+
if (sessionId != null) close.dataset.sessionId = String(sessionId);
|
|
475
|
+
close.hidden = singletonOnly;
|
|
476
|
+
close.disabled = singletonOnly;
|
|
477
|
+
close.title = singletonOnly ? "The only pane cannot be closed" : "Close pane";
|
|
478
|
+
close.setAttribute("aria-label", close.title);
|
|
172
479
|
}
|
|
173
480
|
|
|
174
481
|
function resetPaneContextChip(paneEl) {
|