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
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// Pointer drag controller for presentation views. Captured gestures are
|
|
2
2
|
// source-bound by pointerId and always recompute the release target.
|
|
3
3
|
import { store } from './store.js';
|
|
4
|
+
import { livePaneBinding } from './pane-binding.js';
|
|
5
|
+
import { captureDragPreview, dragPreviewCurrent, dragPreviewPaneAt, renderDragPreview, restoreDragPreview } from './split-view-drag-preview.js';
|
|
4
6
|
import { getCachedSessions } from './sidebar-sessions.js';
|
|
5
7
|
import { showToast } from './utils.js';
|
|
6
8
|
import { currentFolderState, sendFolderOp } from './session-folders.js';
|
|
@@ -29,22 +31,28 @@ function validSession(session) {
|
|
|
29
31
|
function legacyMember(session) { return !!session && session.sessionRole === "worker"; }
|
|
30
32
|
|
|
31
33
|
function onPointerDown(event) {
|
|
32
|
-
if (event.button !== 0 || event.isPrimary === false || store.get('projectSplitViewDrag')) return;
|
|
34
|
+
if (event.button !== 0 || event.isPrimary === false || store.get('projectSplitViewDrag') || store.get('projectSplitViewPending')) return;
|
|
33
35
|
if (!event.target || !event.target.closest) return;
|
|
34
36
|
var paneHeader = event.target.closest(".split-pane-header");
|
|
35
37
|
var row = event.target.closest(".session-item[data-session-id], .session-loop-child[data-session-id]");
|
|
36
38
|
if (!paneHeader && !row) return;
|
|
39
|
+
var workspace = store.get('toolPaneWindowGeometry');
|
|
40
|
+
if (paneHeader && workspace && workspace.windows.some(function (entry) { return !!entry.tool; })) return;
|
|
41
|
+
if (paneHeader && event.target.closest(".split-pane-title, .split-view-runtime, .split-worker-runtime")) return;
|
|
37
42
|
var button = event.target.closest("button");
|
|
38
43
|
if ((paneHeader && button) || (button && button !== row) || event.target.closest("a, input, textarea, select, [contenteditable='true'], .workbench, .split-view-menu, .split-view-arrange, .session-row-actions, .session-close-btn, .session-more-btn")) return;
|
|
39
44
|
var pane = paneHeader && paneHeader.closest('.split-pane');
|
|
45
|
+
if (pane && !livePaneBinding(pane.querySelector('.split-pane-frame'))) return;
|
|
40
46
|
var id = pane ? Number(pane.dataset.sessionId) : row ? Number(row.dataset.sessionId) : 0;
|
|
41
47
|
var source = sessionById(id);
|
|
42
48
|
if (!validSession(source) || legacyMember(source)) return;
|
|
43
49
|
var group = row && row.closest('.split-view-group[data-split-view-id]');
|
|
44
50
|
var view = viewForOrigin(source.sessionOriginId);
|
|
45
|
-
|
|
51
|
+
var drag = { pointerId: event.pointerId, sessionId: source.id, origin: source.sessionOriginId,
|
|
46
52
|
sourceViewId: group ? group.dataset.splitViewId : view && view.id || null, sourceElement: row || paneHeader, startX: event.clientX, startY: event.clientY,
|
|
47
|
-
moved: false, target: null, pointerType: event.pointerType, frames: [] }
|
|
53
|
+
moved: false, target: null, pointerType: event.pointerType, frames: [] };
|
|
54
|
+
captureDragPreview(drag, host);
|
|
55
|
+
store.set({ projectSplitViewDrag: drag });
|
|
48
56
|
}
|
|
49
57
|
|
|
50
58
|
function targetAt(x, y) {
|
|
@@ -59,6 +67,8 @@ function targetAt(x, y) {
|
|
|
59
67
|
}
|
|
60
68
|
var sidebar = sidebarTargetAt(element);
|
|
61
69
|
if (sidebar) return sidebar;
|
|
70
|
+
var snapshot = dragPreviewPaneAt(store.get('projectSplitViewDrag'), x, y);
|
|
71
|
+
if (snapshot) return paneTargetAt(snapshot.pane, x, y, snapshot.rect);
|
|
62
72
|
var pane = element.closest('.split-pane');
|
|
63
73
|
if (!pane || !host.contains(pane) || !pane.isConnected) return null;
|
|
64
74
|
return paneTargetAt(pane, x, y);
|
|
@@ -81,11 +91,11 @@ function sidebarTargetAt(element) {
|
|
|
81
91
|
rect: { left: bounds.left, top: bounds.top, width: bounds.width, height: bounds.height } };
|
|
82
92
|
}
|
|
83
93
|
|
|
84
|
-
function paneTargetAt(pane, x, y) {
|
|
94
|
+
function paneTargetAt(pane, x, y, originalBounds) {
|
|
85
95
|
var id = Number(pane.dataset.sessionId), session = sessionById(id), frame = pane.querySelector('.split-pane-frame');
|
|
86
96
|
if (!validSession(session) || legacyMember(session) || !frame || frame.dataset.projectSlug !== store.get('currentSlug') ||
|
|
87
97
|
frame.dataset.sessionId !== String(id) || frame.dataset.sessionOriginId !== session.sessionOriginId) return null;
|
|
88
|
-
var bounds = pane.getBoundingClientRect(), dx = (x - bounds.left) / Math.max(1, bounds.width), dy = (y - bounds.top) / Math.max(1, bounds.height);
|
|
98
|
+
var bounds = originalBounds || pane.getBoundingClientRect(), dx = (x - bounds.left) / Math.max(1, bounds.width), dy = (y - bounds.top) / Math.max(1, bounds.height);
|
|
89
99
|
var edge = Math.min(dx, 1 - dx, dy, 1 - dy), side = "center";
|
|
90
100
|
if (edge < 0.25) side = edge === dx ? "left" : edge === 1 - dx ? "right" : edge === dy ? "top" : "bottom";
|
|
91
101
|
var view = viewForOrigin(session.sessionOriginId);
|
|
@@ -102,12 +112,13 @@ function fallbackTargetAt(x, y) {
|
|
|
102
112
|
var panes = Array.from(host.querySelectorAll(':scope > .split-pane')), nearest = null, nearestDistance = Infinity;
|
|
103
113
|
panes.forEach(function (pane) {
|
|
104
114
|
if (pane.hidden) return;
|
|
105
|
-
var
|
|
115
|
+
var snapshot = store.get('projectSplitViewDrag'), entry = snapshot && snapshot.preview && snapshot.preview.panes.find(function (item) { return item.pane === pane; });
|
|
116
|
+
var rect = entry ? entry.rect : pane.getBoundingClientRect(), dx = x < rect.left ? rect.left - x : x > rect.right ? x - rect.right : 0;
|
|
106
117
|
var dy = y < rect.top ? rect.top - y : y > rect.bottom ? y - rect.bottom : 0;
|
|
107
118
|
var distance = dx * dx + dy * dy;
|
|
108
119
|
if (distance < nearestDistance) { nearest = pane; nearestDistance = distance; }
|
|
109
120
|
});
|
|
110
|
-
if (nearest) return paneTargetAt(nearest, x, y);
|
|
121
|
+
if (nearest) { var entry = store.get('projectSplitViewDrag').preview.panes.find(function (item) { return item.pane === nearest; }); return paneTargetAt(nearest, x, y, entry && entry.rect); }
|
|
111
122
|
}
|
|
112
123
|
if (!inApp) return null;
|
|
113
124
|
var active = sessionById(Number(store.get('activeSessionId')));
|
|
@@ -123,9 +134,12 @@ function resolveTarget(x, y) { return targetAt(x, y) || fallbackTargetAt(x, y);
|
|
|
123
134
|
function onPointerMove(event) {
|
|
124
135
|
var drag = store.get('projectSplitViewDrag');
|
|
125
136
|
if (!drag || drag.pointerId !== event.pointerId) return;
|
|
137
|
+
if (!dragPreviewCurrent(drag)) { cleanup(true, true); return; }
|
|
126
138
|
if (!drag.moved && Math.hypot(event.clientX - drag.startX, event.clientY - drag.startY) < 6) return;
|
|
127
139
|
if (!drag.moved) {
|
|
128
140
|
drag.moved = true;
|
|
141
|
+
var source = drag.preview.panes.find(function (entry) { return entry.binding && entry.binding.sessionOriginId === drag.origin; });
|
|
142
|
+
if (source) { drag.sourcePane = source.pane; source.pane.classList.add('split-pane-drag-source'); }
|
|
129
143
|
try { document.documentElement.setPointerCapture(event.pointerId); } catch (error) {}
|
|
130
144
|
drag.frames = Array.from(host.querySelectorAll('.split-pane-frame')).map(function (frame) { return { frame: frame, pointerEvents: frame.style.pointerEvents }; });
|
|
131
145
|
drag.frames.forEach(function (entry) { entry.frame.style.pointerEvents = "none"; });
|
|
@@ -138,6 +152,7 @@ function onPointerMove(event) {
|
|
|
138
152
|
|
|
139
153
|
function renderPreview(drag, x, y) {
|
|
140
154
|
clearSidebarPreview();
|
|
155
|
+
var plannedRect = renderDragPreview(drag, drag.target);
|
|
141
156
|
var preview = host.querySelector(':scope > .split-view-drop-preview'), ghost = document.getElementById("split-view-drag-ghost");
|
|
142
157
|
if (!ghost) { ghost = document.createElement("div"); ghost.id = "split-view-drag-ghost"; ghost.className = "split-view-drag-ghost"; ghost.hidden = true; document.body.appendChild(ghost); }
|
|
143
158
|
if (!preview) {
|
|
@@ -188,9 +203,10 @@ function renderPreview(drag, x, y) {
|
|
|
188
203
|
var hostRect = host.getBoundingClientRect();
|
|
189
204
|
preview.style.left = (box.left - hostRect.left) + "px"; preview.style.top = (box.top - hostRect.top) + "px";
|
|
190
205
|
preview.style.width = box.width + "px"; preview.style.height = box.height + "px";
|
|
206
|
+
if (plannedRect) { preview.style.left = plannedRect.left + "px"; preview.style.top = plannedRect.top + "px"; preview.style.width = plannedRect.width + "px"; preview.style.height = plannedRect.height + "px"; }
|
|
191
207
|
preview.dataset.blocked = blocked ? "true" : "false"; preview.hidden = false;
|
|
192
208
|
var label = preview.querySelector(".drop-label");
|
|
193
|
-
if (label) label.textContent = blocked ? "Eight sessions already open" : drag.origin === target.origin ? "Keep this pane" :
|
|
209
|
+
if (label) label.textContent = blocked ? (drag.origin === target.origin ? "Keep this pane" : "Eight sessions already open") : drag.origin === target.origin ? "Keep this pane" :
|
|
194
210
|
target.side === "center" ? (sourceView && targetView && sourceView.id === targetView.id ? "Swap panes" : "Split right") : "Split " + target.side;
|
|
195
211
|
}
|
|
196
212
|
|
|
@@ -199,8 +215,10 @@ function clearSidebarPreview() {
|
|
|
199
215
|
document.querySelectorAll('[data-split-view-drop]').forEach(function (element) { delete element.dataset.splitViewDrop; });
|
|
200
216
|
}
|
|
201
217
|
|
|
202
|
-
export function restorePresentationDrag(drag) {
|
|
218
|
+
export function restorePresentationDrag(drag, keepPreview) {
|
|
203
219
|
if (!drag) return;
|
|
220
|
+
if (drag.sourcePane) drag.sourcePane.classList.remove('split-pane-drag-source');
|
|
221
|
+
restoreDragPreview(drag, keepPreview);
|
|
204
222
|
clearSidebarPreview();
|
|
205
223
|
drag.frames.forEach(function (entry) { if (entry.frame.isConnected) entry.frame.style.pointerEvents = entry.pointerEvents; });
|
|
206
224
|
var preview = host.querySelector(':scope > .split-view-drop-preview'); if (preview) preview.hidden = true;
|
|
@@ -215,23 +233,24 @@ export function restorePresentationDrag(drag) {
|
|
|
215
233
|
}
|
|
216
234
|
}
|
|
217
235
|
|
|
218
|
-
function cleanup(release, suppressClick) {
|
|
236
|
+
function cleanup(release, suppressClick, keepPreview) {
|
|
219
237
|
var drag = store.get('projectSplitViewDrag');
|
|
220
238
|
if (!drag) return;
|
|
221
|
-
restorePresentationDrag(drag);
|
|
239
|
+
restorePresentationDrag(drag, keepPreview);
|
|
222
240
|
if (suppressClick && drag.moved) {
|
|
223
241
|
var token = { pointerId: drag.pointerId, sourceElement: drag.sourceElement, sourceSessionId: drag.sessionId,
|
|
224
242
|
targetOrigin: drag.target && drag.target.origin, until: Date.now() + 250 };
|
|
225
243
|
store.set({ projectSplitViewSuppressClick: token });
|
|
226
244
|
setTimeout(function () { if (store.get('projectSplitViewSuppressClick') === token) store.set({ projectSplitViewSuppressClick: null }); }, 500);
|
|
227
245
|
}
|
|
228
|
-
if (release) try { if (document.documentElement.hasPointerCapture(drag.pointerId)) document.documentElement.releasePointerCapture(drag.pointerId); } catch (error) {}
|
|
229
246
|
store.set({ projectSplitViewDrag: null });
|
|
247
|
+
if (release) try { if (document.documentElement.hasPointerCapture(drag.pointerId)) document.documentElement.releasePointerCapture(drag.pointerId); } catch (error) {}
|
|
230
248
|
}
|
|
231
249
|
|
|
232
250
|
function onPointerUp(event) {
|
|
233
251
|
var drag = store.get('projectSplitViewDrag');
|
|
234
252
|
if (!drag || drag.pointerId !== event.pointerId) return;
|
|
253
|
+
if (!dragPreviewCurrent(drag)) { cleanup(true, true); return; }
|
|
235
254
|
if (!drag.moved) { cleanup(true, false); return; }
|
|
236
255
|
var target = resolveTarget(event.clientX, event.clientY);
|
|
237
256
|
drag.target = target;
|
|
@@ -239,6 +258,11 @@ function onPointerUp(event) {
|
|
|
239
258
|
(store.get('projectSplitViews') || []).some(function (view) { return view.id === target.viewId && view.sessions.length >= 8; })) {
|
|
240
259
|
cleanup(true, true); showToast("Eight sessions are already open. Close a pane to add another.", "warn"); return;
|
|
241
260
|
}
|
|
261
|
+
if (target && !target.folderId && drag.origin !== target.origin && commitDrop) {
|
|
262
|
+
renderDragPreview(drag, target);
|
|
263
|
+
var queued = commitDrop(drag, target);
|
|
264
|
+
cleanup(true, true, queued === true); return;
|
|
265
|
+
}
|
|
242
266
|
cleanup(true, true);
|
|
243
267
|
if (target && target.folderId) {
|
|
244
268
|
var session = sessionById(drag.sessionId);
|
|
@@ -249,7 +273,6 @@ function onPointerUp(event) {
|
|
|
249
273
|
else sendFolderOp(favorite ? { op: 'set_favorite', sessionId: session.id, favorite: true } : { op: 'place_session', sessionId: session.id, folderId: folderId });
|
|
250
274
|
return;
|
|
251
275
|
}
|
|
252
|
-
if (target && drag.origin !== target.origin && commitDrop) commitDrop(drag, target);
|
|
253
276
|
}
|
|
254
277
|
|
|
255
278
|
function onPointerCancel(event) {
|
|
@@ -5,13 +5,25 @@ import { checkComposerDeparture } from './session-rich-drafts.js';
|
|
|
5
5
|
import { showToast } from './utils.js';
|
|
6
6
|
import { listIds, place, swap, pairTree } from './split-view-layout-client.js';
|
|
7
7
|
|
|
8
|
+
// Preview and persistence must resolve the same tree for every drop region.
|
|
9
|
+
export function presentationDropTree(drag, target, sourceView, targetView) {
|
|
10
|
+
if (!target || target.folderId || drag.origin === target.origin) return null;
|
|
11
|
+
var sameView = sourceView && targetView && sourceView.id === targetView.id;
|
|
12
|
+
if (target.sidebar && sameView) return null;
|
|
13
|
+
var side = target.side === "center" ? (sameView ? "center" : "right") : target.side;
|
|
14
|
+
if (!targetView) return pairTree(target.origin, drag.origin, side);
|
|
15
|
+
var result = side === "center" ? swap(targetView.tree, drag.origin, target.origin) : place(targetView.tree, drag.origin, target.origin, side, 0.5);
|
|
16
|
+
return result.ok ? result.tree : null;
|
|
17
|
+
}
|
|
18
|
+
|
|
8
19
|
export function applyPresentationDrop(drag, target, mutation, checkMountedPaneDrafts) {
|
|
9
20
|
var views = store.get('projectSplitViews') || [], sourceView = views.find(function (view) { return view.id === drag.sourceViewId; }), targetView = views.find(function (view) { return view.id === target.viewId; });
|
|
10
21
|
var sessions = getCachedSessions() || [], sourceSession = exactDriverForOrigin(drag.origin, sessions), targetSession = exactDriverForOrigin(target.origin, sessions);
|
|
11
22
|
if (!sourceSession || !targetSession || sourceSession.id !== drag.sessionId) return;
|
|
12
23
|
var sameView = sourceView && targetView && sourceView.id === targetView.id;
|
|
13
24
|
if (target.sidebar && sameView) return;
|
|
14
|
-
var
|
|
25
|
+
var plannedTree = presentationDropTree(drag, target, sourceView, targetView);
|
|
26
|
+
if (!plannedTree) return false;
|
|
15
27
|
function checkDeparture() {
|
|
16
28
|
try {
|
|
17
29
|
if (sourceView && sourceView.id === store.get('projectSplitViewActiveId')) checkMountedPaneDrafts();
|
|
@@ -22,36 +34,27 @@ export function applyPresentationDrop(drag, target, mutation, checkMountedPaneDr
|
|
|
22
34
|
if (!targetView) {
|
|
23
35
|
if (sourceView) {
|
|
24
36
|
if (!checkDeparture()) return;
|
|
25
|
-
var newTree =
|
|
26
|
-
mutation("project_split_view_move", { sourceViewId: sourceView.id, sourceSessionOriginId: drag.origin,
|
|
37
|
+
var newTree = plannedTree;
|
|
38
|
+
return mutation("project_split_view_move", { sourceViewId: sourceView.id, sourceSessionOriginId: drag.origin,
|
|
27
39
|
targetSessionOriginId: target.origin, targetSessionOrigins: listIds(newTree), tree: newTree, layout: "balanced",
|
|
28
40
|
activeSessionOriginId: target.origin, name: "Split view" }, { activateCreatedView: true });
|
|
29
41
|
} else {
|
|
30
42
|
if (!checkDeparture()) return;
|
|
31
|
-
var createdTree =
|
|
32
|
-
mutation("project_split_view_create", { name: "Split view", sessionOrigins: listIds(createdTree), tree: createdTree,
|
|
43
|
+
var createdTree = plannedTree;
|
|
44
|
+
return mutation("project_split_view_create", { name: "Split view", sessionOrigins: listIds(createdTree), tree: createdTree,
|
|
33
45
|
layout: "balanced", activeSessionOriginId: target.origin }, { activateCreatedView: true });
|
|
34
46
|
}
|
|
35
|
-
return;
|
|
36
47
|
}
|
|
37
48
|
if (sourceView && targetView.id !== sourceView.id) {
|
|
38
49
|
if (targetView.sessions.length >= 8) { showToast("Eight sessions are already open. Close a pane to add another.", "warn"); return; }
|
|
39
|
-
var movedTree =
|
|
40
|
-
|
|
41
|
-
mutation("project_split_view_move", { sourceViewId: sourceView.id, sourceSessionOriginId: drag.origin,
|
|
50
|
+
var movedTree = { tree: plannedTree };
|
|
51
|
+
return mutation("project_split_view_move", { sourceViewId: sourceView.id, sourceSessionOriginId: drag.origin,
|
|
42
52
|
targetViewId: targetView.id, targetSessionOrigins: listIds(movedTree.tree), tree: movedTree.tree,
|
|
43
53
|
layout: targetView.layout, activeSessionOriginId: targetView.activeSessionOriginId }, target.sidebar ? { activateCreatedView: true, createdViewId: targetView.id } : null);
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
var nextTree;
|
|
47
|
-
if (side === "center" && sourceView) nextTree = swap(targetView.tree, drag.origin, target.origin).tree;
|
|
48
|
-
else {
|
|
49
|
-
var placed = place(targetView.tree, drag.origin, target.origin, side, 0.5);
|
|
50
|
-
if (!placed.ok) return;
|
|
51
|
-
nextTree = placed.tree;
|
|
52
54
|
}
|
|
55
|
+
var nextTree = plannedTree;
|
|
53
56
|
var origins = listIds(nextTree);
|
|
54
57
|
if (origins.length > 8) { showToast("Eight sessions are already open. Close a pane to add another.", "warn"); return; }
|
|
55
|
-
mutation("project_split_view_update", { id: targetView.id, sessionOrigins: origins, tree: nextTree,
|
|
58
|
+
return mutation("project_split_view_update", { id: targetView.id, sessionOrigins: origins, tree: nextTree,
|
|
56
59
|
layout: targetView.layout, activeSessionOriginId: targetView.activeSessionOriginId }, target.sidebar ? { activateCreatedView: true, createdViewId: targetView.id } : null);
|
|
57
60
|
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { paintLegacyToolPanes, clearToolPaneWindows } from './tool-pane-legacy.js';
|
|
2
|
+
import { toolPaneLayoutTree, paintToolPaneWindows, bindWorkspaceDivider, dockedToolPanes } from './tool-pane-layout.js';
|
|
3
|
+
import { afterPaneMotion } from './split-view-drag-preview.js';
|
|
1
4
|
import { layoutScope, currentLayoutScope, presentationTree } from './split-view-layout-scope.js';
|
|
2
5
|
// Flat, stable pane presentation for persisted binary trees. Geometry is
|
|
3
6
|
// applied to existing direct-child .split-pane nodes; iframes are never moved
|
|
@@ -41,7 +44,6 @@ function relocateStickyStatus(enabled) {
|
|
|
41
44
|
});
|
|
42
45
|
}
|
|
43
46
|
}
|
|
44
|
-
|
|
45
47
|
function dispatch(name, detail) {
|
|
46
48
|
document.dispatchEvent(new CustomEvent(name, { detail: detail }));
|
|
47
49
|
}
|
|
@@ -84,6 +86,7 @@ export function hidePresentationView() {
|
|
|
84
86
|
delete host.dataset.positioned;
|
|
85
87
|
delete host.dataset.singlePane;
|
|
86
88
|
if (!legacySplit) {
|
|
89
|
+
clearToolPaneWindows();
|
|
87
90
|
host.classList.remove("visible");
|
|
88
91
|
if (app) app.classList.remove("split-native-hidden");
|
|
89
92
|
}
|
|
@@ -98,7 +101,7 @@ export function hidePresentationView() {
|
|
|
98
101
|
if (legacySplit) {
|
|
99
102
|
Array.from(host.querySelectorAll(':scope > .split-view-divider, :scope > .split-view-drop-preview')).forEach(function (item) { item.remove(); });
|
|
100
103
|
Array.from(host.querySelectorAll('.split-view-arrange-trigger')).forEach(function (trigger) { trigger.remove(); });
|
|
101
|
-
closePresentationArrange(false);
|
|
104
|
+
closePresentationArrange(false); paintLegacyToolPanes(host);
|
|
102
105
|
return;
|
|
103
106
|
}
|
|
104
107
|
var frames = host.querySelectorAll('.split-pane-frame');
|
|
@@ -169,8 +172,9 @@ function currentSingletonGeometry() {
|
|
|
169
172
|
}
|
|
170
173
|
|
|
171
174
|
function renderCurrentGeometry() {
|
|
175
|
+
if (paintLegacyToolPanes(host)) return;
|
|
172
176
|
var view = currentView(), tree = activeTree();
|
|
173
|
-
if (view && tree) { applyGeometry(view, tree); return; }
|
|
177
|
+
if (view && (tree || !view.sessions.length)) { applyGeometry(view, tree); return; }
|
|
174
178
|
var singleton = currentSingletonGeometry();
|
|
175
179
|
if (singleton) applyGeometry(singleton.view, { id: singleton.origin }, function () {
|
|
176
180
|
var current = currentSingletonGeometry();
|
|
@@ -211,12 +215,14 @@ function applyGeometry(view, tree, stillCurrent) {
|
|
|
211
215
|
});
|
|
212
216
|
var style = window.getComputedStyle(host), left = parseFloat(style.paddingLeft) || 0, top = parseFloat(style.paddingTop) || 0;
|
|
213
217
|
var right = parseFloat(style.paddingRight) || 0, bottom = parseFloat(style.paddingBottom) || 0;
|
|
214
|
-
var
|
|
218
|
+
var windowTree = toolPaneLayoutTree(view, tree);
|
|
219
|
+
var geometry = rectangles(windowTree, Math.max(0, host.clientWidth - left - right), Math.max(0, host.clientHeight - top - bottom), 7);
|
|
220
|
+
paintToolPaneWindows(host, view, tree, windowTree, geometry, { left: left, top: top });
|
|
215
221
|
var focused = store.get('projectSplitViewFocusedOrigin');
|
|
216
222
|
var panes = host.querySelectorAll(':scope > .split-pane');
|
|
217
223
|
for (var i = 0; i < panes.length; i++) {
|
|
218
224
|
var frame = panes[i].querySelector('.split-pane-frame'), origin = panes[i].dataset.presentationOrigin || frame && frame.dataset.sessionOriginId;
|
|
219
|
-
var rect = host.dataset.singlePane === 'true' && panes.length === 1 ?
|
|
225
|
+
var rect = host.dataset.singlePane === 'true' && panes.length === 1 && !dockedToolPanes().length ?
|
|
220
226
|
{ x: 0, y: 0, width: Math.max(0, host.clientWidth - left - right), height: Math.max(0, host.clientHeight - top - bottom) } : geometry.panes[origin];
|
|
221
227
|
if (!rect) continue;
|
|
222
228
|
if (focused && geometry.panes[focused]) {
|
|
@@ -241,11 +247,12 @@ function applyGeometry(view, tree, stillCurrent) {
|
|
|
241
247
|
divider.setAttribute("aria-label", "Resize Split view panels");
|
|
242
248
|
divider.style.left = (left + entry.rect.x) + "px"; divider.style.top = (top + entry.rect.y) + "px";
|
|
243
249
|
divider.style.width = entry.rect.width + "px"; divider.style.height = entry.rect.height + "px";
|
|
244
|
-
|
|
250
|
+
if (dockedToolPanes().length) bindWorkspaceDivider(divider, entry, windowTree);
|
|
251
|
+
else bindDivider(divider, entry, tree, listIds(tree), scope); host.appendChild(divider);
|
|
245
252
|
if (focusedDividerPath && divider.dataset.path === focusedDividerPath) divider.focus();
|
|
246
253
|
}
|
|
247
254
|
ensureDropPreview();
|
|
248
|
-
|
|
255
|
+
afterPaneMotion(host, function () {
|
|
249
256
|
if (resizeToken !== 'split-view-layout-' + geometryToken || (stillCurrent ? !stillCurrent() : !currentLayoutScope(scope))) return;
|
|
250
257
|
resizeFrames.forEach(function (item) {
|
|
251
258
|
var live = item.frame.clayPane && item.frame.clayPane.identity();
|
|
@@ -254,13 +261,11 @@ function applyGeometry(view, tree, stillCurrent) {
|
|
|
254
261
|
});
|
|
255
262
|
});
|
|
256
263
|
}
|
|
257
|
-
|
|
258
264
|
function bindingMatches(left, right) {
|
|
259
265
|
return !!left && !!right && left.sessionId === right.sessionId && left.sessionOriginId === right.sessionOriginId &&
|
|
260
266
|
left.generation === right.generation && left.requestId === right.requestId;
|
|
261
267
|
}
|
|
262
|
-
|
|
263
|
-
function ensureArrangeTrigger(header) {
|
|
268
|
+
export function ensureArrangeTrigger(header) {
|
|
264
269
|
if (!header) return;
|
|
265
270
|
if (!header.querySelector('[data-action="arrange"]')) {
|
|
266
271
|
var trigger = document.createElement("button"); trigger.type = "button"; trigger.className = "split-view-arrange-trigger";
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import { workspaceChanged } from './view-workspace-state.js';
|
|
2
|
+
import { restoreViewPair } from './view-pair-presentation.js';
|
|
3
|
+
import { repaintLegacySplit } from './split-view.js';
|
|
4
|
+
import { validWorkspaceView } from './view-workspace-validation.js';
|
|
5
|
+
import { mutation } from './view-mutations.js';
|
|
6
|
+
import { initSavedWorkspace } from './view-workspace-controller.js';
|
|
1
7
|
import { preserveReconnectingPresentation } from './split-pane-retention.js';
|
|
2
8
|
import { layoutScope, currentLayoutScope, presentationTree } from './split-view-layout-scope.js';
|
|
3
9
|
import { validPresentationClose } from './split-view-presentation-close.js';
|
|
@@ -99,7 +105,7 @@ export function handleProjectSplitViews(msg) {
|
|
|
99
105
|
var invalidView = false;
|
|
100
106
|
msg.views.forEach(function (view) {
|
|
101
107
|
var ids = view && Array.isArray(view.sessions) ? view.sessions.map(function (session) { return session.sessionOriginId; }) : [];
|
|
102
|
-
if (ids.length
|
|
108
|
+
if (ids.length > 8 || viewSessions(view).length !== ids.length || !validateTree(view.tree, ids).ok || !validWorkspaceView(view)) invalidView = true;
|
|
103
109
|
else nextViews.push(view);
|
|
104
110
|
});
|
|
105
111
|
if (invalidView) {
|
|
@@ -115,7 +121,7 @@ export function handleProjectSplitViews(msg) {
|
|
|
115
121
|
if (state.projectSplitViewDrag || state.projectSplitViewDividerDrag) cleanupTransientInteractions(state);
|
|
116
122
|
var activeId = state.projectSplitViewActiveId;
|
|
117
123
|
if (!viewExists(nextViews, activeId)) {
|
|
118
|
-
var restored = restorablePresentation(state, nextViews, getCachedSessions());
|
|
124
|
+
var restored = nextViews.find(function (view) { return view.id === msg.activeViewId && !view.sessions.length; }) || restorablePresentation(state, nextViews, getCachedSessions());
|
|
119
125
|
if (restored) activeId = restored.id;
|
|
120
126
|
}
|
|
121
127
|
var removedActive = activeId && !viewExists(nextViews, activeId) ? activeId : null;
|
|
@@ -126,7 +132,7 @@ export function handleProjectSplitViews(msg) {
|
|
|
126
132
|
var survivor = exactDriverForOrigin(completedPending.meta.activeOrigin, getCachedSessions());
|
|
127
133
|
if (survivor) standaloneTarget = { id: survivor.id, origin: survivor.sessionOriginId, previousSessionId: state.activeSessionId, contextKey: contextKey(state) };
|
|
128
134
|
}
|
|
129
|
-
store.set({ projectSplitViews: nextViews, projectSplitViewRevision: msg.revision, projectSplitViewHydrated: true,
|
|
135
|
+
store.set({ projectSplitViews: nextViews, projectSplitViewRevision: msg.revision, projectSplitViewSavedActiveId: msg.activeViewId || null, projectSplitViewHydrated: true,
|
|
130
136
|
projectSplitViewError: msg.error || "", projectSplitViewStandaloneTarget: standaloneTarget, projectSplitViewActiveId: viewExists(nextViews, activeId) ? activeId : null,
|
|
131
137
|
projectSplitViewFocusedOrigin: viewExists(nextViews, activeId) ? state.projectSplitViewFocusedOrigin : null,
|
|
132
138
|
projectSplitViewPending: readyPending, projectSplitViewPreviewTree: readyPending ? state.projectSplitViewPreviewTree : null,
|
|
@@ -182,22 +188,6 @@ export function organizePresentationView(id, revision, folderId, favorite) {
|
|
|
182
188
|
if (!view || view.revision !== revision) return false;
|
|
183
189
|
return mutation('project_split_view_organize', { id: id, expectedViewRevision: revision, projectSlug: store.get('currentSlug'), folderId: folderId, favorite: favorite });
|
|
184
190
|
}
|
|
185
|
-
function mutation(type, body, meta) {
|
|
186
|
-
var state = store.snap();
|
|
187
|
-
if (!projectReady(state) || !state.projectSplitViewHydrated || state.projectSplitViewError || state.projectSplitViewPending) return false;
|
|
188
|
-
var requestId = "split-view-" + Date.now().toString(36) + "-" + Math.random().toString(36).slice(2, 10);
|
|
189
|
-
var ws = getWs();
|
|
190
|
-
var message = Object.assign({ type: type, requestId: requestId, expectedRevision: state.projectSplitViewRevision }, body || {});
|
|
191
|
-
var pending = { requestId: requestId, type: type, socket: ws, contextKey: contextKey(state), expectedRevision: state.projectSplitViewRevision, meta: meta || null,
|
|
192
|
-
awaitingBroadcast: false, resultRevision: null };
|
|
193
|
-
store.set({ projectSplitViewPending: pending, projectSplitViewError: "" });
|
|
194
|
-
if (!sendMessage(message)) {
|
|
195
|
-
store.set({ projectSplitViewPending: null, projectSplitViewError: "Split view change could not be sent. Refresh before trying again." });
|
|
196
|
-
showToast("Split view change could not be sent. Refresh before trying again.", "error");
|
|
197
|
-
return false;
|
|
198
|
-
}
|
|
199
|
-
return true;
|
|
200
|
-
}
|
|
201
191
|
export function setActiveView(id, preferredOrigin) {
|
|
202
192
|
var state = store.snap(), view = viewExists(state.projectSplitViews, id);
|
|
203
193
|
if (!view) return false;
|
|
@@ -235,6 +225,7 @@ export function switchToStandalone(sessionId) {
|
|
|
235
225
|
return true;
|
|
236
226
|
}
|
|
237
227
|
function renderActive() {
|
|
228
|
+
if (store.get('splitPanes')) { repaintLegacySplit(); return; }
|
|
238
229
|
if (!host || !nativeApp || preserveReconnectingPresentation(host)) return;
|
|
239
230
|
var state = store.snap(), view = viewExists(state.projectSplitViews, state.projectSplitViewActiveId);
|
|
240
231
|
if (state.splitIdentityBlockedSocket === getWs()) { hidePresentationView(); return; }
|
|
@@ -246,9 +237,11 @@ function renderActive() {
|
|
|
246
237
|
}
|
|
247
238
|
var singleton = currentSingletonPresentation(state, getCachedSessions());
|
|
248
239
|
if (singleton) {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
240
|
+
if (state.projectSplitViewHydrated && !state.projectSplitViewPending && !state.projectSplitViewError) mutation("project_split_view_create", { name: "View", sessionOrigins: [singleton.origin], tree: { id: singleton.origin }, layout: "balanced", activeSessionOriginId: singleton.origin }, { activateCreatedView: true });
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
if (state.projectSplitViewHydrated && projectReady(state) && !(getCachedSessions() || []).length && !state.projectSplitViewPending && !state.projectSplitViewError) {
|
|
244
|
+
mutation('project_split_view_create', { name: 'View', sessionOrigins: [], tree: null, layout: 'balanced', activeSessionOriginId: null }, { activateCreatedView: true });
|
|
252
245
|
return;
|
|
253
246
|
}
|
|
254
247
|
if (state.projectSplitViewSingletonOrigin) store.set({ projectSplitViewSingletonOrigin: null });
|
|
@@ -257,10 +250,11 @@ function renderActive() {
|
|
|
257
250
|
return;
|
|
258
251
|
}
|
|
259
252
|
if (state.projectSplitViewSingletonOrigin) store.set({ projectSplitViewSingletonOrigin: null });
|
|
253
|
+
if (restoreViewPair(view)) return;
|
|
260
254
|
var sessions = viewSessions(view);
|
|
261
255
|
var tree = presentationTree(view);
|
|
262
256
|
var ids = listIds(tree);
|
|
263
|
-
if (sessions.length !== view.sessions.length || ids.length
|
|
257
|
+
if (sessions.length !== view.sessions.length || ids.length > 8 || !validateTree(tree, ids).ok) return;
|
|
264
258
|
if (stickyContainer && mainPanels) mainPanels.appendChild(stickyContainer);
|
|
265
259
|
renderPresentationView(view, tree, sessions);
|
|
266
260
|
}
|
|
@@ -424,14 +418,9 @@ function onClosePane(event) {
|
|
|
424
418
|
if (!session || !view.sessions.some(function (item) { return item.sessionOriginId === session.sessionOriginId; })) return;
|
|
425
419
|
try { checkMountedPaneDrafts(); } catch (error) { showToast(error.message, "warn"); return; }
|
|
426
420
|
var origins = view.sessions.map(function (item) { return item.sessionOriginId; }).filter(function (origin) { return origin !== session.sessionOriginId; });
|
|
427
|
-
if (origins.length < 2) {
|
|
428
|
-
var remaining = view.sessions.filter(function (item) { return item.sessionOriginId !== session.sessionOriginId; })[0];
|
|
429
|
-
if (remaining) mutation("project_split_view_separate", { id: view.id }, { separateViewId: view.id, activeOrigin: remaining.sessionOriginId });
|
|
430
|
-
return;
|
|
431
|
-
}
|
|
432
421
|
var nextTree = remove(view.tree, session.sessionOriginId);
|
|
433
|
-
if (!
|
|
434
|
-
var nextActive = view.activeSessionOriginId === session.sessionOriginId ? origins[0] : view.activeSessionOriginId;
|
|
422
|
+
if (!validateTree(nextTree, origins).ok) return;
|
|
423
|
+
var nextActive = view.activeSessionOriginId === session.sessionOriginId ? origins[0] || null : view.activeSessionOriginId;
|
|
435
424
|
mutation("project_split_view_update", { id: view.id, sessionOrigins: origins, tree: nextTree,
|
|
436
425
|
layout: view.layout, activeSessionOriginId: nextActive }, { closedOrigin: session.sessionOriginId, activeOrigin: nextActive });
|
|
437
426
|
}
|
|
@@ -442,13 +431,15 @@ function onFocus(event) {
|
|
|
442
431
|
if (event.detail && event.detail.focused && !source) return;
|
|
443
432
|
store.set({ projectSplitViewFocusedOrigin: event.detail && event.detail.focused ? source.sessionOriginId : null });
|
|
444
433
|
renderActive();
|
|
434
|
+
if (!store.get('savedWorkspaceApplying')) workspaceChanged();
|
|
445
435
|
}
|
|
446
436
|
function init(hostElement) {
|
|
447
437
|
host = hostElement; nativeApp = document.getElementById("app"); mainPanels = document.getElementById("main-panels");
|
|
448
438
|
stickyContainer = document.getElementById("sticky-notes-container");
|
|
449
439
|
if (stickyContainer) { stickyHome = stickyContainer.parentNode; stickyAnchor = stickyContainer.nextSibling; }
|
|
450
440
|
initPresentationRenderer(host);
|
|
451
|
-
|
|
441
|
+
initSavedWorkspace();
|
|
442
|
+
initPresentationDrag(host, function (drag, target) { return applyPresentationDrop(drag, target, mutation, checkMountedPaneDrafts); });
|
|
452
443
|
initSplitViewCreateMenu();
|
|
453
444
|
document.addEventListener('clay-split-view-create', function (event) { handleSplitViewCreateEvent(event, mutation, checkMountedPaneDrafts); });
|
|
454
445
|
document.addEventListener("click", onClick, true);
|
|
@@ -476,7 +467,7 @@ function init(hostElement) {
|
|
|
476
467
|
state.paneBindingSessions !== previous.paneBindingSessions || state.sessionActivatedProjectSlug !== previous.sessionActivatedProjectSlug) renderActive();
|
|
477
468
|
if (state.activeSessionId !== previous.activeSessionId && state.projectSplitViewActiveId) {
|
|
478
469
|
var activeView = viewExists(state.projectSplitViews, state.projectSplitViewActiveId);
|
|
479
|
-
if (activeView && !activeView.sessions.some(function (session) { return session.id === state.activeSessionId; })) {
|
|
470
|
+
if (activeView && activeView.sessions.length && !activeView.sessions.some(function (session) { return session.id === state.activeSessionId; })) {
|
|
480
471
|
store.set({ projectSplitViewActiveId: null, projectSplitViewPreviewTree: null });
|
|
481
472
|
}
|
|
482
473
|
}
|
|
@@ -493,6 +484,7 @@ export function applyReviewedSplitView(target) {
|
|
|
493
484
|
var view = viewExists(store.get('projectSplitViews'), target.view.id);
|
|
494
485
|
if (!projectReady(store.snap()) || store.get('projectSplitViewPending') || !view || JSON.stringify(view) !== JSON.stringify(target.view)) return false;
|
|
495
486
|
if (!setActiveView(view.id, view.activeSessionOriginId)) return false;
|
|
496
|
-
|
|
487
|
+
store.set({ savedWorkspaceApplying: true });
|
|
488
|
+
try { onFocus({ detail: { focused: !!target.focusOrigin, sessionOriginId: target.focusOrigin } }); } finally { store.set({ savedWorkspaceApplying: false }); }
|
|
497
489
|
return true;
|
|
498
490
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { syncPairView, pairPresentationPanes, pairViewCapacity } from './view-pair-presentation.js';
|
|
2
|
+
import { paintLegacyToolPanes } from './tool-pane-legacy.js';
|
|
1
3
|
import { adoptDocumentSource } from './clay-studio-document.js';
|
|
2
4
|
import { trustedStudioFrame } from './clay-studio-render.js';
|
|
3
5
|
import { handlePaneBrowserMessage } from './pane-browser-bridge.js';
|
|
@@ -185,7 +187,8 @@ function renderSplit(split) {
|
|
|
185
187
|
singleton || split && split.panes && split.panes.length >= 2 || !!state.projectSplitViewActiveId);
|
|
186
188
|
// The exact singleton presentation is verified before the redundant cache catches up.
|
|
187
189
|
if (singleton) { renderPresentationSplitView(); return; }
|
|
188
|
-
|
|
190
|
+
var savedPair = split && split.panes && syncPairView();
|
|
191
|
+
if (split && split.panes && !savedPair && store.get('projectSplitViewActiveId')) {
|
|
189
192
|
store.set({ projectSplitViewActiveId: null, projectSplitViewFocusedOrigin: null, projectSplitViewPreviewTree: null });
|
|
190
193
|
}
|
|
191
194
|
var expectedPresentationContext = [store.get('currentSlug') || "", store.get('currentProjectOwnerId') || "", store.get('myUserId') || "", store.get('projectSplitViewSocketGeneration') || 0].join("|");
|
|
@@ -213,8 +216,10 @@ function renderSplit(split) {
|
|
|
213
216
|
placeStickyNotesOverlay(true);
|
|
214
217
|
nativeApp.classList.add("split-native-hidden");
|
|
215
218
|
host.classList.add("visible");
|
|
219
|
+
if (savedPair) panes = pairPresentationPanes(panes);
|
|
216
220
|
reconcileSplitPanes(host, panes, function (pane) { return createSplitPane(pane, closePane); }, updateSplitPaneMetadata);
|
|
217
221
|
syncPairChrome(host, split);
|
|
222
|
+
paintLegacyToolPanes(host);
|
|
218
223
|
refreshIcons();
|
|
219
224
|
}
|
|
220
225
|
|
|
@@ -246,7 +251,7 @@ function openSplit(side, draggedId) {
|
|
|
246
251
|
|
|
247
252
|
export function openGroup(group) {
|
|
248
253
|
if (!canLeavePanes()) return false;
|
|
249
|
-
if (!group || !Array.isArray(group.members) || group.members.length < 2) return false;
|
|
254
|
+
if (!group || !Array.isArray(group.members) || group.members.length < 2 || !pairViewCapacity(group)) return false;
|
|
250
255
|
var memberIds = splitGroupMemberIds(group);
|
|
251
256
|
if (memberIds.length !== group.members.length) return false;
|
|
252
257
|
for (var mi = 0; mi < memberIds.length; mi++) if (!sessionById(memberIds[mi])) return false;
|
|
@@ -491,3 +496,5 @@ export function initSplitView() {
|
|
|
491
496
|
initSplitViewPresentations(host);
|
|
492
497
|
renderSplit(store.get('splitPanes'));
|
|
493
498
|
}
|
|
499
|
+
|
|
500
|
+
export function repaintLegacySplit() { if (store.get('splitPanes')) renderSplit(store.get('splitPanes')); }
|
|
@@ -14,7 +14,7 @@ import { enhanceClayLogLinks } from './clay-log-links.js';
|
|
|
14
14
|
import { closeHumanNote } from './sticky-notes-actions.js';
|
|
15
15
|
import { send, getNoteUiState } from './sticky-notes-shared.js';
|
|
16
16
|
import { listNoteData, focusNoteOnCanvas, hideNotes, showNotes } from './sticky-notes.js';
|
|
17
|
-
import { claimRightWorkbench, registerRightWorkbench, releaseRightWorkbench } from './right-workbench.js';
|
|
17
|
+
import { handlesWorkbenchKey, claimRightWorkbench, registerRightWorkbench, releaseRightWorkbench } from './right-workbench.js';
|
|
18
18
|
|
|
19
19
|
var panel = null;
|
|
20
20
|
var gridEl = null;
|
|
@@ -427,7 +427,7 @@ export function isNotesBrowserOpen() {
|
|
|
427
427
|
export function initNotesBrowser() {
|
|
428
428
|
registerRightWorkbench("notes-browser", closeNotesBrowser);
|
|
429
429
|
document.addEventListener("keydown", function (e) {
|
|
430
|
-
if (e.key !== "Escape") return;
|
|
430
|
+
if (e.key !== "Escape" || !handlesWorkbenchKey("notes-browser", e)) return;
|
|
431
431
|
if (deleteDialog && !deleteDialog.classList.contains("hidden")) return;
|
|
432
432
|
if (!store.get('notesBrowserOpen')) return;
|
|
433
433
|
closeNotesBrowser();
|