clay-server 5.2.1-beta.1 → 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/sdk-bridge.js +16 -3
- 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/lib/yoke/adapters/codex.js +1 -0
- package/lib/yoke/codex-app-server.js +3 -1
- package/lib/yoke/codex-idle-recovery.js +73 -20
- package/lib/yoke/codex-recovery-admission.js +65 -4
- package/package.json +6 -3
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
// Pure projection of sidebar units into folder sections. No DOM, no store.
|
|
2
2
|
//
|
|
3
3
|
// A unit is one organizable root: a standalone session or a Driver with all of
|
|
4
|
-
// its Workers
|
|
5
|
-
//
|
|
6
|
-
// always live with the ordinary, unfiled sessions.
|
|
4
|
+
// its Workers, or a saved presentation view. Saved views own their folder and
|
|
5
|
+
// Favorite metadata. Unkeyed legacy groups and loop runs remain Unfiled.
|
|
7
6
|
|
|
8
7
|
export var FAVORITES_ID = "favorites";
|
|
9
8
|
export var UNFILED_ID = "unfiled";
|
|
@@ -48,7 +47,8 @@ export function isFavorite(state, key) {
|
|
|
48
47
|
|
|
49
48
|
export function containerOf(state, unit) {
|
|
50
49
|
if (unit.key === null) return UNFILED_ID;
|
|
51
|
-
var
|
|
50
|
+
var group = unit.item && unit.item.type === "split-group" && unit.item.group && unit.item.group.presentation ? unit.item.group : null;
|
|
51
|
+
var id = group ? group.folderId : state.assignments[unit.key];
|
|
52
52
|
for (var i = 0; i < state.folders.length; i++) if (state.folders[i].id === id) return id;
|
|
53
53
|
return UNFILED_ID;
|
|
54
54
|
}
|
|
@@ -66,7 +66,8 @@ export function buildLayout(units, state, options) {
|
|
|
66
66
|
var ordinary = [];
|
|
67
67
|
for (var i = 0; i < units.length; i++) {
|
|
68
68
|
// The same unit may appear twice: once as a favorite, once in its folder.
|
|
69
|
-
|
|
69
|
+
var group = units[i].item && units[i].item.type === "split-group" && units[i].item.group && units[i].item.group.presentation ? units[i].item.group : null;
|
|
70
|
+
if (group ? group.favorite === true : isFavorite(state, units[i].key)) favorites.push(units[i]);
|
|
70
71
|
ordinary.push(units[i]);
|
|
71
72
|
}
|
|
72
73
|
var result = {
|
|
@@ -117,7 +118,7 @@ export function containerKeys(layout, containerId) {
|
|
|
117
118
|
if (layout.sections[i].id === containerId) list = layout.sections[i].units;
|
|
118
119
|
}
|
|
119
120
|
}
|
|
120
|
-
return list.filter(function (u) { return u.key !== null; }).map(function (u) { return u.key; });
|
|
121
|
+
return list.filter(function (u) { return u.key !== null && !(u.item && u.item.type === "split-group" && u.item.group && u.item.group.presentation); }).map(function (u) { return u.key; });
|
|
121
122
|
}
|
|
122
123
|
|
|
123
124
|
export var SORT_OPTIONS = [
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { store } from './store.js';
|
|
2
|
+
import { paneMessageBinding } from './pane-binding.js';
|
|
3
|
+
import { acceptsPaneSearchResults } from './pane-search-receipt.js';
|
|
4
|
+
|
|
5
|
+
function publishPaneSearchStatus(query, status) {
|
|
6
|
+
if (!store.get('paneMode') || window.parent === window) return;
|
|
7
|
+
window.parent.postMessage({ type: "clay-pane-search-status", paneBinding: paneMessageBinding(), query: query,
|
|
8
|
+
status: status, open: store.get('paneSearchOpen') === true }, window.location.origin);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function updatePaneSearchStatus(countElement, query, status) {
|
|
12
|
+
if (countElement) countElement.textContent = status;
|
|
13
|
+
publishPaneSearchStatus(query, status);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function beginPaneSearch(query) {
|
|
17
|
+
var binding = paneMessageBinding(), epoch = (Number(store.get('paneSearchEpoch')) || 0) + 1;
|
|
18
|
+
store.set({ paneSearchEpoch: epoch, paneSearchReceipt: binding ? { binding: binding, epoch: epoch, query: query } : null });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function endPaneSearch() {
|
|
22
|
+
store.set({ paneSearchOpen: false, paneSearchReceipt: null, paneSearchEpoch: (Number(store.get('paneSearchEpoch')) || 0) + 1 });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function acceptsSessionSearchResults(state, msg, query) {
|
|
26
|
+
if (state.paneMode && (!state.paneSearchOpen || !acceptsPaneSearchResults(state, msg))) return false;
|
|
27
|
+
return msg.query === query;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export { updatePaneSearchStatus, beginPaneSearch, endPaneSearch, acceptsSessionSearchResults };
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
// --- In-session search (Cmd+F / Ctrl+F) ---
|
|
2
2
|
import { escapeHtml } from './utils.js';
|
|
3
3
|
import { iconHtml, refreshIcons } from './icons.js';
|
|
4
|
+
import { store } from './store.js';
|
|
5
|
+
import { paneMessageBinding } from './pane-binding.js';
|
|
6
|
+
import { updatePaneSearchStatus, beginPaneSearch, endPaneSearch, acceptsSessionSearchResults } from './session-search-pane-state.js';
|
|
4
7
|
|
|
5
8
|
var ctx = null;
|
|
6
9
|
var searchBarEl = null;
|
|
@@ -19,9 +22,20 @@ var serverHits = []; // full history hits from server
|
|
|
19
22
|
var serverTotal = 0;
|
|
20
23
|
var pendingScrollTarget = null;
|
|
21
24
|
|
|
25
|
+
function setSearchStatus(text) {
|
|
26
|
+
updatePaneSearchStatus(matchCountEl, currentQuery, text);
|
|
27
|
+
}
|
|
28
|
+
|
|
22
29
|
function initSessionSearch(context) {
|
|
23
30
|
ctx = context;
|
|
24
31
|
createSearchBar();
|
|
32
|
+
var searchBinding = paneMessageBinding();
|
|
33
|
+
store.subscribe(function () {
|
|
34
|
+
var nextBinding = paneMessageBinding();
|
|
35
|
+
if (searchBinding === nextBinding) return;
|
|
36
|
+
searchBinding = nextBinding;
|
|
37
|
+
if (store.get('paneSearchOpen') || currentQuery || matches.length || serverHits.length) closeSearch();
|
|
38
|
+
});
|
|
25
39
|
document.addEventListener("keydown", function (e) {
|
|
26
40
|
var isMod = e.metaKey || e.ctrlKey;
|
|
27
41
|
if (isMod && e.key === "f") {
|
|
@@ -90,11 +104,16 @@ function createSearchBar() {
|
|
|
90
104
|
}
|
|
91
105
|
|
|
92
106
|
function isSearchOpen() {
|
|
107
|
+
if (store.get('paneMode')) return store.get('paneSearchOpen') === true;
|
|
93
108
|
return searchBarEl && !searchBarEl.classList.contains("hidden");
|
|
94
109
|
}
|
|
95
110
|
|
|
96
111
|
function openSearch(prefill) {
|
|
97
112
|
if (!searchBarEl) return;
|
|
113
|
+
if (store.get('paneMode') && window.parent !== window) {
|
|
114
|
+
window.parent.postMessage({ type: "clay-pane-search-open", paneBinding: paneMessageBinding() }, window.location.origin);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
98
117
|
searchBarEl.classList.remove("hidden");
|
|
99
118
|
var btn = document.getElementById("find-in-session-btn");
|
|
100
119
|
if (btn) btn.classList.add("active");
|
|
@@ -111,6 +130,7 @@ function openSearch(prefill) {
|
|
|
111
130
|
|
|
112
131
|
function closeSearch() {
|
|
113
132
|
if (!searchBarEl) return;
|
|
133
|
+
endPaneSearch();
|
|
114
134
|
searchBarEl.classList.add("hidden");
|
|
115
135
|
var btn = document.getElementById("find-in-session-btn");
|
|
116
136
|
if (btn) btn.classList.remove("active");
|
|
@@ -121,7 +141,27 @@ function closeSearch() {
|
|
|
121
141
|
currentMatchIndex = -1;
|
|
122
142
|
serverHits = [];
|
|
123
143
|
serverTotal = 0;
|
|
124
|
-
|
|
144
|
+
setSearchStatus("");
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function controlPaneSearch(action, query) {
|
|
148
|
+
if (!store.get('paneMode')) return false;
|
|
149
|
+
if (action === "close") { closeSearch(); return true; }
|
|
150
|
+
if (action === "open") {
|
|
151
|
+
store.set({ paneSearchOpen: true });
|
|
152
|
+
searchInputEl.value = String(query || "");
|
|
153
|
+
performSearch(searchInputEl.value);
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
if (!store.get('paneSearchOpen')) return false;
|
|
157
|
+
if (action === "query") {
|
|
158
|
+
searchInputEl.value = String(query || "");
|
|
159
|
+
performSearch(searchInputEl.value);
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
if (action === "next") { goToNextMatch(); return true; }
|
|
163
|
+
if (action === "previous") { goToPrevMatch(); return true; }
|
|
164
|
+
return false;
|
|
125
165
|
}
|
|
126
166
|
|
|
127
167
|
function toggleSearch() {
|
|
@@ -140,9 +180,10 @@ function performSearch(query) {
|
|
|
140
180
|
serverHits = [];
|
|
141
181
|
serverTotal = 0;
|
|
142
182
|
currentQuery = query.trim();
|
|
183
|
+
if (store.get('paneMode')) beginPaneSearch(currentQuery);
|
|
143
184
|
|
|
144
185
|
if (!currentQuery) {
|
|
145
|
-
|
|
186
|
+
setSearchStatus("");
|
|
146
187
|
return;
|
|
147
188
|
}
|
|
148
189
|
|
|
@@ -171,16 +212,15 @@ function highlightLoadedMessages() {
|
|
|
171
212
|
if (matches.length > 0) {
|
|
172
213
|
currentMatchIndex = 0;
|
|
173
214
|
setActiveMatch(0);
|
|
174
|
-
|
|
215
|
+
setSearchStatus("1 / " + matches.length);
|
|
175
216
|
} else {
|
|
176
|
-
|
|
217
|
+
setSearchStatus("Searching...");
|
|
177
218
|
}
|
|
178
219
|
}
|
|
179
220
|
|
|
180
221
|
// Handle server response with full-history search results
|
|
181
222
|
function handleFindInSessionResults(msg) {
|
|
182
|
-
if (!isSearchOpen()) return;
|
|
183
|
-
if (msg.query !== currentQuery) return; // stale
|
|
223
|
+
if (!isSearchOpen() || !acceptsSessionSearchResults(store.snap(), msg, currentQuery)) return;
|
|
184
224
|
|
|
185
225
|
serverHits = msg.hits || [];
|
|
186
226
|
serverTotal = msg.total || 0;
|
|
@@ -191,13 +231,13 @@ function handleFindInSessionResults(msg) {
|
|
|
191
231
|
clearHighlights();
|
|
192
232
|
highlightLoadedMessages();
|
|
193
233
|
if (matches.length > 0) {
|
|
194
|
-
|
|
234
|
+
setSearchStatus("1 / " + matches.length + " (" + serverHits.length + " total)");
|
|
195
235
|
} else {
|
|
196
|
-
|
|
236
|
+
setSearchStatus(serverHits.length + " matches");
|
|
197
237
|
}
|
|
198
238
|
buildTimeline();
|
|
199
239
|
} else {
|
|
200
|
-
|
|
240
|
+
setSearchStatus("No results");
|
|
201
241
|
}
|
|
202
242
|
}
|
|
203
243
|
|
|
@@ -441,16 +481,16 @@ function goToNextMatch() {
|
|
|
441
481
|
if (matches.length === 0) return;
|
|
442
482
|
currentMatchIndex = (currentMatchIndex + 1) % matches.length;
|
|
443
483
|
setActiveMatch(currentMatchIndex);
|
|
444
|
-
|
|
445
|
-
(serverHits.length > matches.length ? " (" + serverHits.length + " total)" : "");
|
|
484
|
+
setSearchStatus((currentMatchIndex + 1) + " / " + matches.length +
|
|
485
|
+
(serverHits.length > matches.length ? " (" + serverHits.length + " total)" : ""));
|
|
446
486
|
}
|
|
447
487
|
|
|
448
488
|
function goToPrevMatch() {
|
|
449
489
|
if (matches.length === 0) return;
|
|
450
490
|
currentMatchIndex = (currentMatchIndex - 1 + matches.length) % matches.length;
|
|
451
491
|
setActiveMatch(currentMatchIndex);
|
|
452
|
-
|
|
453
|
-
(serverHits.length > matches.length ? " (" + serverHits.length + " total)" : "");
|
|
492
|
+
setSearchStatus((currentMatchIndex + 1) + " / " + matches.length +
|
|
493
|
+
(serverHits.length > matches.length ? " (" + serverHits.length + " total)" : ""));
|
|
454
494
|
}
|
|
455
495
|
|
|
456
496
|
export { initSessionSearch, openSearch, closeSearch, toggleSearch, isSearchOpen, handleFindInSessionResults, onHistoryPrepended };
|
|
@@ -47,7 +47,7 @@ import { ordinarySessionListSessions } from './session-list-visibility.js';
|
|
|
47
47
|
import { formatSessionActivity } from './session-activity-tooltip.js';
|
|
48
48
|
import { bindSessionTitleMarquee } from './session-title-marquee.js';
|
|
49
49
|
import { summarizeSidebarItems } from './sidebar-session-counts.js';
|
|
50
|
-
import { cancelSessionInlineRename,
|
|
50
|
+
import { cancelSessionInlineRename, reconcileSessionContextMenu } from './session-context-menu.js';
|
|
51
51
|
|
|
52
52
|
// --- Mobile state ---
|
|
53
53
|
var mobileChatSheetOpen = false;
|
|
@@ -447,7 +447,7 @@ function createMobileSessionItem(s, options) {
|
|
|
447
447
|
el.addEventListener("contextmenu", function (event) {
|
|
448
448
|
event.preventDefault();
|
|
449
449
|
event.stopPropagation();
|
|
450
|
-
openSessionContextMenu(el, s);
|
|
450
|
+
openSessionContextMenu(el, s, event.clientX || event.clientY ? { x: event.clientX, y: event.clientY } : null);
|
|
451
451
|
});
|
|
452
452
|
|
|
453
453
|
(function (session, worker) {
|
|
@@ -775,7 +775,6 @@ export function refreshMobileChatSheet() {
|
|
|
775
775
|
var sessionListEl = sheet.querySelector(".mobile-chat-session-list");
|
|
776
776
|
if (!sessionListEl) return;
|
|
777
777
|
|
|
778
|
-
closeSessionContextMenu(false);
|
|
779
778
|
cancelSessionInlineRename(false);
|
|
780
779
|
|
|
781
780
|
// Update chips: active state and processing dots
|
|
@@ -815,6 +814,7 @@ export function refreshMobileChatSheet() {
|
|
|
815
814
|
renderMobileSessionsInto(sessionListEl);
|
|
816
815
|
|
|
817
816
|
refreshIcons();
|
|
817
|
+
reconcileSessionContextMenu();
|
|
818
818
|
}
|
|
819
819
|
|
|
820
820
|
function renderSheetMateProfile(listEl) {
|
|
@@ -1020,6 +1020,7 @@ function showWorktreeModal(parentSlug, parentName) {
|
|
|
1020
1020
|
export function renderIconStrip(projects, currentSlug) {
|
|
1021
1021
|
cachedProjectList = projects;
|
|
1022
1022
|
cachedCurrentSlug = currentSlug;
|
|
1023
|
+
if (store.get('paneMode')) return;
|
|
1023
1024
|
|
|
1024
1025
|
var container = document.getElementById("icon-strip-projects");
|
|
1025
1026
|
if (!container) return;
|
|
@@ -65,7 +65,7 @@ export function unitsFromItems(items) {
|
|
|
65
65
|
var item = items[i];
|
|
66
66
|
var data = item.type === "session" || item.type === "driver-hierarchy" ? item.data : null;
|
|
67
67
|
units.push({
|
|
68
|
-
key: data && typeof data.id === "number" ? data.id : null,
|
|
68
|
+
key: item.type === "split-group" && item.group && item.group.presentation ? "split-view:" + item.group.id : data && typeof data.id === "number" ? data.id : null,
|
|
69
69
|
title: data ? data.title : (item.type === "split-group" ? (item.group && item.group.name) : (item.type === "loop" ? item.loopId : "")),
|
|
70
70
|
createdAt: data ? data.createdAt || 0 : 0,
|
|
71
71
|
lastActivity: data ? (data.lastActivity || 0) : (item.lastActivity || 0),
|
|
@@ -275,9 +275,9 @@ function renderUnit(unit, containerId, ctx) {
|
|
|
275
275
|
wrapper.className = "session-folder-unit";
|
|
276
276
|
if (unit.key) {
|
|
277
277
|
wrapper.dataset.unitKey = String(unit.key);
|
|
278
|
-
if (ctx.surface === "desktop") wireUnitDrop(wrapper, containerId, unit.key);
|
|
278
|
+
if (ctx.surface === "desktop" && typeof unit.key === "number") wireUnitDrop(wrapper, containerId, unit.key);
|
|
279
279
|
}
|
|
280
|
-
wrapper.appendChild(ctx.renderItem(unit.item));
|
|
280
|
+
wrapper.appendChild(ctx.renderItem(unit.item, containerId, ctx.surface));
|
|
281
281
|
return wrapper;
|
|
282
282
|
}
|
|
283
283
|
|
|
@@ -13,6 +13,8 @@ import { showConfirm } from './app-misc.js';
|
|
|
13
13
|
import { getUpcomingSchedules } from './scheduler.js';
|
|
14
14
|
import { refreshMobileChatSheet } from './sidebar-mobile.js';
|
|
15
15
|
import { openGroup, openWorkerWithDriver, separateGroup } from './split-view.js';
|
|
16
|
+
import { presentationViewForSidebar } from './split-view-presentations.js';
|
|
17
|
+
import { renderPresentationSplitViewItem } from './split-view-sidebar-renderer.js';
|
|
16
18
|
import { groupedSessionIds } from './split-group-helpers.js';
|
|
17
19
|
import { resolvePreferredVendor } from './default-vendor.js';
|
|
18
20
|
import {
|
|
@@ -21,6 +23,7 @@ import {
|
|
|
21
23
|
} from './sidebar-session-folders-ui.js';
|
|
22
24
|
import { renderFolderToolbar, captureFolderInputs, folderToolbarNeedsRender } from './session-folder-toolbar.js';
|
|
23
25
|
import { captureFolderCollapseAnimations } from './session-folder-collapse.js';
|
|
26
|
+
import { closeFolderMenu, reconcileFolderMenu } from './session-folder-context.js';
|
|
24
27
|
import { getListSearchQuery, getListSearchMatchIds, applyListSearchResults, filterItemsBySearch } from './session-list-search.js';
|
|
25
28
|
import { expectCreatedSession } from './session-create.js';
|
|
26
29
|
import { isMateWorkspace } from './project-mate-navigation.js';
|
|
@@ -39,6 +42,8 @@ import {
|
|
|
39
42
|
cancelSessionInlineRename,
|
|
40
43
|
closeSessionContextMenu,
|
|
41
44
|
mountSessionContextMenu,
|
|
45
|
+
positionSessionContextMenu,
|
|
46
|
+
reconcileSessionContextMenu,
|
|
42
47
|
startSessionInlineRename
|
|
43
48
|
} from './session-context-menu.js';
|
|
44
49
|
|
|
@@ -203,6 +208,8 @@ export function initSidebarSessions() {
|
|
|
203
208
|
var b = prev.sessionCreate;
|
|
204
209
|
if ((!a !== !b || (a && b && a.folderId !== b.folderId)) && getSessionListEl()) renderSessionList(null);
|
|
205
210
|
if (state.splitPanes !== prev.splitPanes) renderSessionList(null);
|
|
211
|
+
if (state.projectSplitViews !== prev.projectSplitViews || state.projectSplitViewActiveId !== prev.projectSplitViewActiveId ||
|
|
212
|
+
state.projectSplitViewError !== prev.projectSplitViewError || state.projectSplitViewPending !== prev.projectSplitViewPending) renderSessionList(null);
|
|
206
213
|
});
|
|
207
214
|
|
|
208
215
|
// --- Resume session picker ---
|
|
@@ -234,8 +241,17 @@ export function getExpandedLoopRuns() {
|
|
|
234
241
|
|
|
235
242
|
// --- Context menu ---
|
|
236
243
|
|
|
237
|
-
function showSessionCtxMenu(anchorBtn, sessionId, title, cliSid, sessionData) {
|
|
244
|
+
function showSessionCtxMenu(anchorBtn, sessionId, title, cliSid, sessionData, point) {
|
|
238
245
|
closeSessionContextMenu(false);
|
|
246
|
+
closeFolderMenu(false);
|
|
247
|
+
var origin = sessionData && sessionData.sessionOriginId, owner = sessionData && sessionData.ownerId;
|
|
248
|
+
var rowSelector = anchorBtn.classList.contains('mobile-session-item') ? '.mobile-session-item' : '.session-item';
|
|
249
|
+
var wasFavorite = isFavoriteSession(sessionData);
|
|
250
|
+
function currentAnchor() {
|
|
251
|
+
var live = cachedSessions.find(function (item) { return item.id === sessionId && item.sessionOriginId === origin && item.ownerId === owner && item.title === title; });
|
|
252
|
+
if (!live || isFavoriteSession(live) !== wasFavorite) return null;
|
|
253
|
+
return anchorBtn.isConnected ? anchorBtn : document.querySelector(rowSelector + '[data-session-id="' + sessionId + '"]');
|
|
254
|
+
}
|
|
239
255
|
|
|
240
256
|
var menu = document.createElement("div");
|
|
241
257
|
menu.className = "session-ctx-menu";
|
|
@@ -268,8 +284,8 @@ function showSessionCtxMenu(anchorBtn, sessionId, title, cliSid, sessionData) {
|
|
|
268
284
|
renameItem.innerHTML = iconHtml("pencil") + " <span>Rename</span>";
|
|
269
285
|
renameItem.addEventListener("click", function (e) {
|
|
270
286
|
e.stopPropagation();
|
|
271
|
-
closeSessionContextMenu(false);
|
|
272
|
-
startSessionInlineRename(
|
|
287
|
+
var row = currentAnchor(); closeSessionContextMenu(false);
|
|
288
|
+
if (row) startSessionInlineRename(row, sessionData);
|
|
273
289
|
});
|
|
274
290
|
menu.appendChild(renameItem);
|
|
275
291
|
|
|
@@ -305,26 +321,13 @@ function showSessionCtxMenu(anchorBtn, sessionId, title, cliSid, sessionData) {
|
|
|
305
321
|
}
|
|
306
322
|
|
|
307
323
|
document.body.appendChild(menu);
|
|
308
|
-
mountSessionContextMenu(menu, anchorBtn, sessionId);
|
|
324
|
+
mountSessionContextMenu(menu, anchorBtn, sessionId, { resolveAnchor: currentAnchor });
|
|
309
325
|
refreshIcons();
|
|
310
|
-
|
|
311
|
-
// Position: fixed relative to the anchor button
|
|
312
|
-
requestAnimationFrame(function () {
|
|
313
|
-
var btnRect = anchorBtn.getBoundingClientRect();
|
|
314
|
-
menu.style.position = "fixed";
|
|
315
|
-
menu.style.top = (btnRect.bottom + 2) + "px";
|
|
316
|
-
menu.style.right = (window.innerWidth - btnRect.right) + "px";
|
|
317
|
-
menu.style.left = "auto";
|
|
318
|
-
// If menu overflows below viewport, flip up
|
|
319
|
-
var menuRect = menu.getBoundingClientRect();
|
|
320
|
-
if (menuRect.bottom > window.innerHeight - 8) {
|
|
321
|
-
menu.style.top = (btnRect.top - menuRect.height - 2) + "px";
|
|
322
|
-
}
|
|
323
|
-
});
|
|
326
|
+
positionSessionContextMenu(menu, anchorBtn, point);
|
|
324
327
|
}
|
|
325
328
|
|
|
326
|
-
export function openSessionContextMenu(anchor, session) {
|
|
327
|
-
showSessionCtxMenu(anchor, session.id, session.title, session.cliSessionId, session);
|
|
329
|
+
export function openSessionContextMenu(anchor, session, point) {
|
|
330
|
+
showSessionCtxMenu(anchor, session.id, session.title, session.cliSessionId, session, point);
|
|
328
331
|
}
|
|
329
332
|
|
|
330
333
|
function showSplitGroupCtxMenu(anchor, group) {
|
|
@@ -867,9 +870,14 @@ function renderSessionItem(s, options) {
|
|
|
867
870
|
return function(e) {
|
|
868
871
|
e.preventDefault();
|
|
869
872
|
e.stopPropagation();
|
|
870
|
-
showSessionCtxMenu(anchor, id, title, cliSid, sData);
|
|
873
|
+
showSessionCtxMenu(anchor, id, title, cliSid, sData, e.clientX || e.clientY ? { x: e.clientX, y: e.clientY } : null);
|
|
871
874
|
};
|
|
872
875
|
})(s.id, s.title, s.cliSessionId, el, s));
|
|
876
|
+
el.addEventListener('keydown', function (event) {
|
|
877
|
+
if (event.key !== 'ContextMenu' && !(event.shiftKey && event.key === 'F10')) return;
|
|
878
|
+
if (event.target.closest('input, textarea, [contenteditable="true"]')) return;
|
|
879
|
+
event.preventDefault(); event.stopPropagation(); showSessionCtxMenu(el, s.id, s.title, s.cliSessionId, s);
|
|
880
|
+
});
|
|
873
881
|
|
|
874
882
|
// Unread badge
|
|
875
883
|
var unreadBadge = document.createElement("span");
|
|
@@ -975,6 +983,9 @@ function sessionRenderFingerprint(sessions) {
|
|
|
975
983
|
}
|
|
976
984
|
|
|
977
985
|
export function renderSessionList(sessions) {
|
|
986
|
+
// Pane activation consumes this exact list, but its sidebar is parent-owned.
|
|
987
|
+
// Avoid building every hidden session/folder/Worker row in each iframe.
|
|
988
|
+
if (store.get('paneMode')) { if (sessions) cachedSessions = sessions; return; }
|
|
978
989
|
if (sessions) {
|
|
979
990
|
// A reconnect and a streaming turn both re-send this list unchanged;
|
|
980
991
|
// rebuilding the sidebar for an identical frame is what made it flicker.
|
|
@@ -983,7 +994,6 @@ export function renderSessionList(sessions) {
|
|
|
983
994
|
cachedSessions = sessions;
|
|
984
995
|
}
|
|
985
996
|
|
|
986
|
-
closeSessionContextMenu(false);
|
|
987
997
|
cancelSessionInlineRename(false);
|
|
988
998
|
|
|
989
999
|
// Remember the inline folder draft before either surface is rebuilt: the mobile
|
|
@@ -1007,6 +1017,26 @@ export function renderSessionList(sessions) {
|
|
|
1007
1017
|
hierarchySessionIds.forEach(function (id) { groupedIds.delete(id); });
|
|
1008
1018
|
var sessionsById = new Map();
|
|
1009
1019
|
for (var si = 0; si < visibleSessions.length; si++) sessionsById.set(visibleSessions[si].id, visibleSessions[si]);
|
|
1020
|
+
var presentationItems = [];
|
|
1021
|
+
var presentationViews = store.get('projectSplitViews') || [];
|
|
1022
|
+
for (var pvi = 0; pvi < presentationViews.length; pvi++) {
|
|
1023
|
+
var presentationView = presentationViewForSidebar(presentationViews[pvi].id);
|
|
1024
|
+
if (!presentationView || !Array.isArray(presentationView.sessions) || presentationView.sessions.length < 2 || presentationView.sessions.length > 8) continue;
|
|
1025
|
+
var presentationMembers = [], validPresentation = true, presentationActivity = 0;
|
|
1026
|
+
for (var pmi = 0; pmi < presentationView.sessions.length; pmi++) {
|
|
1027
|
+
var presentationRef = presentationView.sessions[pmi], presentationSession = null;
|
|
1028
|
+
for (var psi = 0; psi < visibleSessions.length; psi++) {
|
|
1029
|
+
if (visibleSessions[psi].id === presentationRef.id && visibleSessions[psi].sessionOriginId === presentationRef.sessionOriginId) presentationSession = visibleSessions[psi];
|
|
1030
|
+
}
|
|
1031
|
+
if (!presentationSession || presentationSession.sessionRole === "worker" || presentationSession.isMate || presentationSession.isTui ||
|
|
1032
|
+
groupedIds.has(presentationSession.id)) { validPresentation = false; break; }
|
|
1033
|
+
presentationMembers.push(presentationSession); presentationActivity = Math.max(presentationActivity, presentationSession.lastActivity || 0);
|
|
1034
|
+
}
|
|
1035
|
+
if (!validPresentation) continue;
|
|
1036
|
+
for (var pgm = 0; pgm < presentationMembers.length; pgm++) groupedIds.add(presentationMembers[pgm].id);
|
|
1037
|
+
presentationItems.push({ type: "split-group", group: Object.assign({ presentation: true }, presentationView), members: presentationMembers,
|
|
1038
|
+
lastActivity: presentationActivity });
|
|
1039
|
+
}
|
|
1010
1040
|
var loopGroups = {}; // groupKey -> [sessions]
|
|
1011
1041
|
var normalSessions = [];
|
|
1012
1042
|
for (var i = 0; i < visibleSessions.length; i++) {
|
|
@@ -1056,6 +1086,7 @@ export function renderSessionList(sessions) {
|
|
|
1056
1086
|
lastActivity: splitLastActivity,
|
|
1057
1087
|
});
|
|
1058
1088
|
}
|
|
1089
|
+
for (var pitem = 0; pitem < presentationItems.length; pitem++) items.push(presentationItems[pitem]);
|
|
1059
1090
|
var groupKeys = Object.keys(loopGroups);
|
|
1060
1091
|
for (var k = 0; k < groupKeys.length; k++) {
|
|
1061
1092
|
var gk = groupKeys[k];
|
|
@@ -1079,9 +1110,9 @@ export function renderSessionList(sessions) {
|
|
|
1079
1110
|
searching: matchIds !== null,
|
|
1080
1111
|
matchIds: matchIds,
|
|
1081
1112
|
sessions: cachedSessions,
|
|
1082
|
-
renderItem: function (it) {
|
|
1113
|
+
renderItem: function (it, containerId, surface) {
|
|
1083
1114
|
if (it.type === "loop") return renderLoopGroup(it.loopId, it.children, it.groupKey) || document.createElement("div");
|
|
1084
|
-
if (it.type === "split-group") return renderSplitGroupItem(it.group, it.members);
|
|
1115
|
+
if (it.type === "split-group") return it.group.presentation ? renderPresentationSplitViewItem(it.group, it.members, renderSessionItem, containerId, surface) : renderSplitGroupItem(it.group, it.members);
|
|
1085
1116
|
if (it.type === "driver-hierarchy") return renderDesktopDriverHierarchy(it.root, renderSessionItem, rerender, matchIds);
|
|
1086
1117
|
if (it.type === "orphan-workers") return document.createElement("div");
|
|
1087
1118
|
return renderSessionItem(it.data);
|
|
@@ -1101,6 +1132,8 @@ export function renderSessionList(sessions) {
|
|
|
1101
1132
|
renderOrdinarySections(layout, folderCtx, regularContainer);
|
|
1102
1133
|
getSessionListEl().appendChild(regularContainer);
|
|
1103
1134
|
refreshIcons();
|
|
1135
|
+
reconcileSessionContextMenu();
|
|
1136
|
+
reconcileFolderMenu();
|
|
1104
1137
|
if (updatePageTitle) updatePageTitle();
|
|
1105
1138
|
// Recorded from the sessions actually rendered, so a null-argument re-render
|
|
1106
1139
|
// driven by other state refreshes the fingerprint rather than stranding it.
|
|
@@ -63,11 +63,27 @@ export function closeSidebar() {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
export function toggleSidebarCollapse() {
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
var layout = document.getElementById("layout");
|
|
67
|
+
if (!layout && ctx) layout = ctx.$("layout");
|
|
68
|
+
if (!layout) return;
|
|
68
69
|
var collapsed = layout.classList.toggle("sidebar-collapsed");
|
|
69
70
|
try { localStorage.setItem("sidebar-collapsed", collapsed ? "1" : ""); } catch (e) {}
|
|
70
|
-
|
|
71
|
+
updateSidebarToggleState(collapsed);
|
|
72
|
+
if (ctx) setTimeout(function () { syncResizeHandles(); }, 210);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function updateSidebarToggleState(collapsed) {
|
|
76
|
+
var buttons = document.querySelectorAll("#sidebar-toggle-btn, #sidebar-expand-btn, #mate-sidebar-toggle-btn, #sidebar-shell-expand-btn");
|
|
77
|
+
for (var i = 0; i < buttons.length; i++) {
|
|
78
|
+
buttons[i].setAttribute("aria-expanded", collapsed ? "false" : "true");
|
|
79
|
+
buttons[i].title = collapsed ? "Open sidebar" : "Collapse sidebar";
|
|
80
|
+
buttons[i].setAttribute("aria-label", collapsed ? "Open sidebar" : "Collapse sidebar");
|
|
81
|
+
if (buttons[i].id === "sidebar-shell-expand-btn") {
|
|
82
|
+
var splitVisible = document.getElementById("split-host");
|
|
83
|
+
var desktop = !window.matchMedia || window.matchMedia("(min-width: 769px)").matches;
|
|
84
|
+
buttons[i].hidden = !collapsed || !desktop || !splitVisible || !splitVisible.classList.contains("visible");
|
|
85
|
+
}
|
|
86
|
+
}
|
|
71
87
|
}
|
|
72
88
|
|
|
73
89
|
export function initSidebar(_ctx) {
|
|
@@ -106,6 +122,7 @@ export function initSidebar(_ctx) {
|
|
|
106
122
|
ctx.$("layout").classList.add("sidebar-collapsed");
|
|
107
123
|
}
|
|
108
124
|
} catch (e) {}
|
|
125
|
+
updateSidebarToggleState(ctx.$("layout").classList.contains("sidebar-collapsed"));
|
|
109
126
|
|
|
110
127
|
if (ctx.newSessionBtn) {
|
|
111
128
|
ctx.newSessionBtn.addEventListener("click", function () {
|
|
@@ -39,7 +39,7 @@ export function splitGroupRoles(group) {
|
|
|
39
39
|
var driverId = pair.driverId;
|
|
40
40
|
var workerIds = hasWorkerIds ? (Array.isArray(pair.workerIds) ? pair.workerIds.slice() : []) :
|
|
41
41
|
(pair.workerId !== undefined ? [pair.workerId] : []);
|
|
42
|
-
if (!Number.isInteger(driverId) || workerIds.length < 1
|
|
42
|
+
if (!Number.isInteger(driverId) || workerIds.length < 1) return null;
|
|
43
43
|
if (group.members.indexOf(driverId) === -1) return null;
|
|
44
44
|
var ordered = [driverId];
|
|
45
45
|
for (var i = 0; i < workerIds.length; i++) {
|
|
@@ -26,7 +26,7 @@ export function reconcileSplitIdentity(state, previous, host) {
|
|
|
26
26
|
|
|
27
27
|
// The initial owner response can arrive after history and split metadata.
|
|
28
28
|
// Wait for it so identity cleanup cannot discard panes we just restored.
|
|
29
|
-
export function restoreSplitGroup(
|
|
29
|
+
export function restoreSplitGroup() {
|
|
30
30
|
var state = store.snap();
|
|
31
31
|
if (state.authIdentityLoaded === false || state.isMultiUserMode && !state.myUserId) return;
|
|
32
32
|
if (!isCurrentProjectSessionReady(state, getWs())) return;
|
|
@@ -36,6 +36,10 @@ export function restoreSplitGroup(openGroup) {
|
|
|
36
36
|
return;
|
|
37
37
|
}
|
|
38
38
|
if (state.paneMode) return;
|
|
39
|
+
var activePresentation = (state.projectSplitViews || []).find(function (view) { return view.id === state.projectSplitViewActiveId; });
|
|
40
|
+
if (activePresentation && activePresentation.sessions.some(function (session) {
|
|
41
|
+
return session.id === state.activeSessionId || session.sessionOriginId === state.projectSplitViewFocusedOrigin;
|
|
42
|
+
})) return;
|
|
39
43
|
if (split) {
|
|
40
44
|
var reconciliation = reconcileRestoredSplit(split, state.splitGroups);
|
|
41
45
|
if (reconciliation.action === "clear") {
|
|
@@ -55,14 +59,7 @@ export function restoreSplitGroup(openGroup) {
|
|
|
55
59
|
}
|
|
56
60
|
return;
|
|
57
61
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
for (var i = 0; i < groups.length; i++) {
|
|
62
|
-
var members = groups[i].members || [];
|
|
63
|
-
if (members.indexOf(activeId) !== -1) {
|
|
64
|
-
openGroup(groups[i]);
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
62
|
+
// An execution group is not a presentation choice. Restore an explicitly
|
|
63
|
+
// saved legacy split above, but keep an ordinary selected Driver in its
|
|
64
|
+
// single Pane even when it owns Workers. Worker Controls opens the pair.
|
|
68
65
|
}
|
|
@@ -325,3 +325,21 @@ export function syncPairChrome(host, split) {
|
|
|
325
325
|
livePane.querySelector(".split-pane-header").appendChild(live);
|
|
326
326
|
}
|
|
327
327
|
}
|
|
328
|
+
|
|
329
|
+
// A reconciled pane may move from a legacy Worker pair into a presentation
|
|
330
|
+
// Split view. Remove pair-only role and runtime chrome before refreshing the
|
|
331
|
+
// new session metadata; legacy rendering adds it again immediately afterward.
|
|
332
|
+
export function clearPanePairChrome(paneEl) {
|
|
333
|
+
if (!paneEl) return;
|
|
334
|
+
paneEl.classList.remove("split-pane-role-driver");
|
|
335
|
+
paneEl.classList.remove("split-pane-role-worker");
|
|
336
|
+
if (paneEl.style.removeProperty) {
|
|
337
|
+
paneEl.style.removeProperty("--split-pane-order");
|
|
338
|
+
paneEl.style.removeProperty("--split-worker-row");
|
|
339
|
+
}
|
|
340
|
+
[".split-pair-role", ".split-pair-live", ".split-pair-set-driver", ".split-worker-runtime"].forEach(function (selector) {
|
|
341
|
+
Array.from(paneEl.querySelectorAll(selector)).forEach(function (item) { item.remove(); });
|
|
342
|
+
});
|
|
343
|
+
var header = paneEl.querySelector(".split-pane-header");
|
|
344
|
+
if (header) header.classList.remove("has-worker-runtime");
|
|
345
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { store } from './store.js';
|
|
2
|
+
import { getCachedSessions } from './sidebar-sessions.js';
|
|
3
|
+
import { livePaneBinding, paneTarget, samePaneTarget } from './pane-binding.js';
|
|
4
|
+
|
|
5
|
+
function exactReadyPane(paneEl, frame) {
|
|
6
|
+
if (!paneEl || !frame || !frame.clayPane || !store.get('connected') || frame.dataset.requestedSessionId) return false;
|
|
7
|
+
var live = frame.clayPane.identity();
|
|
8
|
+
var sessionId = Number(paneEl.dataset.sessionId);
|
|
9
|
+
var target = live && paneTarget(store.snap(), getCachedSessions(), live.sessionId);
|
|
10
|
+
return !!(live && live.ready && sessionId === live.sessionId && Number(frame.dataset.sessionId) === live.sessionId &&
|
|
11
|
+
live.binding && live.binding.sessionOriginId === frame.dataset.sessionOriginId &&
|
|
12
|
+
samePaneTarget(target, live.binding) && livePaneBinding(frame));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function syncPaneHeaderState(paneEl) {
|
|
16
|
+
var header = paneEl && paneEl.querySelector('.split-pane-header');
|
|
17
|
+
var frame = paneEl && paneEl.querySelector('.split-pane-frame');
|
|
18
|
+
if (!header || !frame) return false;
|
|
19
|
+
var ready = exactReadyPane(paneEl, frame);
|
|
20
|
+
header.setAttribute('aria-busy', ready ? 'false' : 'true');
|
|
21
|
+
header.dataset.paneLoading = ready ? 'false' : 'true';
|
|
22
|
+
header.inert = !ready;
|
|
23
|
+
var actions = header.querySelectorAll('.split-pane-info, .split-pane-search, .split-pane-context, .split-pane-sidebar, .split-view-arrange-trigger');
|
|
24
|
+
for (var i = 0; i < actions.length; i++) {
|
|
25
|
+
var action = actions[i];
|
|
26
|
+
if (!ready) {
|
|
27
|
+
if (action.dataset.panePriorDisabled == null) action.dataset.panePriorDisabled = action.disabled ? 'true' : 'false';
|
|
28
|
+
action.disabled = true;
|
|
29
|
+
} else if (action.dataset.panePriorDisabled != null) {
|
|
30
|
+
action.disabled = action.dataset.panePriorDisabled === 'true';
|
|
31
|
+
delete action.dataset.panePriorDisabled;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
var close = paneEl.querySelector('.split-pane-close');
|
|
35
|
+
if (close) {
|
|
36
|
+
var host = paneEl.parentNode;
|
|
37
|
+
var singletonOnly = !!host && host.id === 'split-host' && host.dataset && host.dataset.singlePane === 'true' &&
|
|
38
|
+
host.querySelectorAll('.split-pane').length === 1;
|
|
39
|
+
close.hidden = singletonOnly;
|
|
40
|
+
close.disabled = !ready || singletonOnly;
|
|
41
|
+
}
|
|
42
|
+
var title = paneEl.querySelector('.split-pane-title');
|
|
43
|
+
if (title) title.setAttribute('aria-disabled', ready ? 'false' : 'true');
|
|
44
|
+
return ready;
|
|
45
|
+
}
|