@tutti-os/workbench-surface 0.0.230 → 0.0.232
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +19 -5
- package/dist/index.js +775 -187
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -2546,10 +2546,13 @@ import { createPortal } from "react-dom";
|
|
|
2546
2546
|
|
|
2547
2547
|
// src/react/WorkbenchWindowFrame.tsx
|
|
2548
2548
|
import {
|
|
2549
|
+
createContext as createContext2,
|
|
2549
2550
|
useCallback as useCallback6,
|
|
2551
|
+
useContext as useContext2,
|
|
2550
2552
|
useLayoutEffect as useLayoutEffect3,
|
|
2551
2553
|
useMemo as useMemo4,
|
|
2552
|
-
useRef as useRef3
|
|
2554
|
+
useRef as useRef3,
|
|
2555
|
+
useSyncExternalStore
|
|
2553
2556
|
} from "react";
|
|
2554
2557
|
import { createI18nRuntime } from "@tutti-os/ui-i18n-runtime";
|
|
2555
2558
|
import { Checkbox } from "@tutti-os/ui-system";
|
|
@@ -2919,6 +2922,10 @@ var defaultWindowChromeI18n = createWorkbenchWindowChromeI18nRuntime(
|
|
|
2919
2922
|
dictionaries: [workbenchWindowChromeI18nResources.en]
|
|
2920
2923
|
})
|
|
2921
2924
|
);
|
|
2925
|
+
var WorkbenchWindowPresentationVisibilityContext = createContext2(true);
|
|
2926
|
+
function useWorkbenchWindowPresentationVisibility() {
|
|
2927
|
+
return useContext2(WorkbenchWindowPresentationVisibilityContext);
|
|
2928
|
+
}
|
|
2922
2929
|
function resolveWorkbenchNodeLaunchSource(data) {
|
|
2923
2930
|
if (data && typeof data === "object" && "launchSource" in data && typeof data.launchSource === "string" && data.launchSource.length > 0) {
|
|
2924
2931
|
return data.launchSource;
|
|
@@ -2934,9 +2941,10 @@ function resolveWorkbenchNodeTypeId(data) {
|
|
|
2934
2941
|
function WorkbenchWindowFrame({
|
|
2935
2942
|
children,
|
|
2936
2943
|
edgeSnapEnabled = false,
|
|
2937
|
-
|
|
2944
|
+
genieNodeVisibility,
|
|
2938
2945
|
hiddenMounted = false,
|
|
2939
2946
|
interactive = true,
|
|
2947
|
+
minimizeNodeToAnchor: minimizeNodeToAnchorProp,
|
|
2940
2948
|
node,
|
|
2941
2949
|
presentation = null,
|
|
2942
2950
|
renderActions,
|
|
@@ -2971,10 +2979,23 @@ function WorkbenchWindowFrame({
|
|
|
2971
2979
|
controller.commands.focusNode(node.id);
|
|
2972
2980
|
controller.commands.applySnapTarget(node.id, "top");
|
|
2973
2981
|
};
|
|
2974
|
-
const
|
|
2982
|
+
const subscribeGenieVisibility = useCallback6(
|
|
2983
|
+
(listener) => genieNodeVisibility.subscribe(node.id, listener),
|
|
2984
|
+
[genieNodeVisibility, node.id]
|
|
2985
|
+
);
|
|
2986
|
+
const readGenieVisibility = useCallback6(
|
|
2987
|
+
() => genieNodeVisibility.getSnapshot(node.id),
|
|
2988
|
+
[genieNodeVisibility, node.id]
|
|
2989
|
+
);
|
|
2990
|
+
const isGenieHidden = useSyncExternalStore(
|
|
2991
|
+
subscribeGenieVisibility,
|
|
2992
|
+
readGenieVisibility,
|
|
2993
|
+
readGenieVisibility
|
|
2994
|
+
);
|
|
2995
|
+
const minimizeNodeToAnchorRef = useRef3(minimizeNodeToAnchorProp);
|
|
2975
2996
|
useLayoutEffect3(() => {
|
|
2976
|
-
minimizeNodeToAnchorRef.current =
|
|
2977
|
-
}, [
|
|
2997
|
+
minimizeNodeToAnchorRef.current = minimizeNodeToAnchorProp;
|
|
2998
|
+
}, [minimizeNodeToAnchorProp]);
|
|
2978
2999
|
const minimizeNodeToAnchor = useCallback6(
|
|
2979
3000
|
(nodeID, minimize) => {
|
|
2980
3001
|
minimizeNodeToAnchorRef.current(nodeID, minimize);
|
|
@@ -3043,6 +3064,7 @@ function WorkbenchWindowFrame({
|
|
|
3043
3064
|
const presentationMode = presentation?.mode ?? null;
|
|
3044
3065
|
const presentationFrame = presentation?.frameByNodeId.get(node.id) ?? null;
|
|
3045
3066
|
const isPresentationHidden = presentationMode === "mission-control" && !presentation?.visibleNodeIds.has(node.id);
|
|
3067
|
+
const isWindowPresentationVisible = !hiddenMounted && !isGenieHidden && presentationMode === null;
|
|
3046
3068
|
const presentationInteraction = interactive && presentationMode === "mission-control" && !isPresentationHidden ? presentation?.interaction ?? null : null;
|
|
3047
3069
|
const isMissionControlSelected = presentationInteraction?.selectedNodeIds.has(node.id) ?? false;
|
|
3048
3070
|
const presentationScale = presentationMode === "mission-control" && presentationFrame ? Math.min(
|
|
@@ -3065,7 +3087,7 @@ function WorkbenchWindowFrame({
|
|
|
3065
3087
|
className: "workbench-window-shell",
|
|
3066
3088
|
"data-focused": isFocused ? "true" : "false",
|
|
3067
3089
|
"data-display-mode": node.displayMode,
|
|
3068
|
-
"data-genie-state":
|
|
3090
|
+
"data-genie-state": isGenieHidden ? "hidden" : "visible",
|
|
3069
3091
|
"data-launch-source": resolveWorkbenchNodeLaunchSource(node.data),
|
|
3070
3092
|
"data-minimized-mount": hiddenMounted ? "hidden" : "visible",
|
|
3071
3093
|
"data-presentation-mode": presentationMode ?? "default",
|
|
@@ -3120,7 +3142,13 @@ function WorkbenchWindowFrame({
|
|
|
3120
3142
|
] })
|
|
3121
3143
|
}
|
|
3122
3144
|
),
|
|
3123
|
-
/* @__PURE__ */ jsx7("div", { className: "workbench-window__body", children
|
|
3145
|
+
/* @__PURE__ */ jsx7("div", { className: "workbench-window__body", children: /* @__PURE__ */ jsx7(
|
|
3146
|
+
WorkbenchWindowPresentationVisibilityContext.Provider,
|
|
3147
|
+
{
|
|
3148
|
+
value: isWindowPresentationVisible,
|
|
3149
|
+
children
|
|
3150
|
+
}
|
|
3151
|
+
) })
|
|
3124
3152
|
]
|
|
3125
3153
|
}
|
|
3126
3154
|
),
|
|
@@ -3169,6 +3197,7 @@ function ResizeHandle({
|
|
|
3169
3197
|
}
|
|
3170
3198
|
|
|
3171
3199
|
// src/react/renderedNodeIds.ts
|
|
3200
|
+
var emptyNodeIDs = [];
|
|
3172
3201
|
function createRenderedWorkbenchNodeIDsSelector(shouldKeepMinimizedNodeMounted = void 0) {
|
|
3173
3202
|
let previousIDs = null;
|
|
3174
3203
|
return (state) => {
|
|
@@ -3182,6 +3211,50 @@ function createRenderedWorkbenchNodeIDsSelector(shouldKeepMinimizedNodeMounted =
|
|
|
3182
3211
|
return nextIDs;
|
|
3183
3212
|
};
|
|
3184
3213
|
}
|
|
3214
|
+
function createWorkbenchNodeLayerNodeIDsSelector({
|
|
3215
|
+
missionControl,
|
|
3216
|
+
resolveWindowSurfaceLayer,
|
|
3217
|
+
shouldKeepMinimizedNodeMounted
|
|
3218
|
+
}) {
|
|
3219
|
+
const selectRenderedNodeIDs = createRenderedWorkbenchNodeIDsSelector(
|
|
3220
|
+
shouldKeepMinimizedNodeMounted
|
|
3221
|
+
);
|
|
3222
|
+
let previousSelection = null;
|
|
3223
|
+
return (state) => {
|
|
3224
|
+
const renderedNodeIDs = selectRenderedNodeIDs(state);
|
|
3225
|
+
let nextDefaultNodeIDs = renderedNodeIDs;
|
|
3226
|
+
let nextDialogPopoverNodeIDs = emptyNodeIDs;
|
|
3227
|
+
if (resolveWindowSurfaceLayer && !missionControl) {
|
|
3228
|
+
const nodeByID = new Map(state.nodes.map((node) => [node.id, node]));
|
|
3229
|
+
const defaultNodeIDs = [];
|
|
3230
|
+
const dialogPopoverNodeIDs = [];
|
|
3231
|
+
for (const nodeID of renderedNodeIDs) {
|
|
3232
|
+
const node = nodeByID.get(nodeID);
|
|
3233
|
+
if (node && resolveWindowSurfaceLayer({ node }) === "dialog-popover") {
|
|
3234
|
+
dialogPopoverNodeIDs.push(nodeID);
|
|
3235
|
+
} else {
|
|
3236
|
+
defaultNodeIDs.push(nodeID);
|
|
3237
|
+
}
|
|
3238
|
+
}
|
|
3239
|
+
nextDefaultNodeIDs = preserveStringArrayIdentity(
|
|
3240
|
+
previousSelection?.defaultNodeIDs,
|
|
3241
|
+
defaultNodeIDs
|
|
3242
|
+
);
|
|
3243
|
+
nextDialogPopoverNodeIDs = preserveStringArrayIdentity(
|
|
3244
|
+
previousSelection?.dialogPopoverNodeIDs,
|
|
3245
|
+
dialogPopoverNodeIDs
|
|
3246
|
+
);
|
|
3247
|
+
}
|
|
3248
|
+
if (previousSelection?.defaultNodeIDs === nextDefaultNodeIDs && previousSelection.dialogPopoverNodeIDs === nextDialogPopoverNodeIDs) {
|
|
3249
|
+
return previousSelection;
|
|
3250
|
+
}
|
|
3251
|
+
previousSelection = {
|
|
3252
|
+
defaultNodeIDs: nextDefaultNodeIDs,
|
|
3253
|
+
dialogPopoverNodeIDs: nextDialogPopoverNodeIDs
|
|
3254
|
+
};
|
|
3255
|
+
return previousSelection;
|
|
3256
|
+
};
|
|
3257
|
+
}
|
|
3185
3258
|
function shouldRenderWorkbenchNode(node, shouldKeepMinimizedNodeMounted) {
|
|
3186
3259
|
return !node.isMinimized || shouldKeepMinimizedNodeMounted?.(node) === true;
|
|
3187
3260
|
}
|
|
@@ -3191,6 +3264,9 @@ function stringArraysEqual(left, right) {
|
|
|
3191
3264
|
}
|
|
3192
3265
|
return left.every((value, index) => value === right[index]);
|
|
3193
3266
|
}
|
|
3267
|
+
function preserveStringArrayIdentity(previous, next) {
|
|
3268
|
+
return previous && stringArraysEqual(previous, next) ? previous : next;
|
|
3269
|
+
}
|
|
3194
3270
|
|
|
3195
3271
|
// src/react/WorkbenchNodeLayer.tsx
|
|
3196
3272
|
import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
@@ -3210,46 +3286,32 @@ function WorkbenchNodeLayer({
|
|
|
3210
3286
|
windowChromeMode,
|
|
3211
3287
|
windowChromeI18n
|
|
3212
3288
|
}) {
|
|
3213
|
-
const
|
|
3214
|
-
() =>
|
|
3215
|
-
|
|
3289
|
+
const selectNodeLayerNodeIDs = useMemo5(
|
|
3290
|
+
() => createWorkbenchNodeLayerNodeIDsSelector({
|
|
3291
|
+
missionControl: presentation?.mode === "mission-control",
|
|
3292
|
+
resolveWindowSurfaceLayer,
|
|
3293
|
+
shouldKeepMinimizedNodeMounted
|
|
3294
|
+
}),
|
|
3295
|
+
[
|
|
3296
|
+
presentation?.mode,
|
|
3297
|
+
resolveWindowSurfaceLayer,
|
|
3298
|
+
shouldKeepMinimizedNodeMounted
|
|
3299
|
+
]
|
|
3216
3300
|
);
|
|
3217
|
-
const
|
|
3218
|
-
|
|
3301
|
+
const { defaultNodeIDs, dialogPopoverNodeIDs } = useWorkbenchSelector(
|
|
3302
|
+
selectNodeLayerNodeIDs
|
|
3219
3303
|
);
|
|
3220
|
-
const { defaultNodeIDs, dialogPopoverNodeIDs } = useWorkbenchSelector((state) => {
|
|
3221
|
-
if (!resolveWindowSurfaceLayer || presentation?.mode === "mission-control") {
|
|
3222
|
-
return {
|
|
3223
|
-
defaultNodeIDs: nodeIDs,
|
|
3224
|
-
dialogPopoverNodeIDs: []
|
|
3225
|
-
};
|
|
3226
|
-
}
|
|
3227
|
-
const nodeByID = new Map(state.nodes.map((node) => [node.id, node]));
|
|
3228
|
-
const nextDefaultNodeIDs = [];
|
|
3229
|
-
const nextDialogPopoverNodeIDs = [];
|
|
3230
|
-
for (const nodeID of nodeIDs) {
|
|
3231
|
-
const node = nodeByID.get(nodeID);
|
|
3232
|
-
if (node && resolveWindowSurfaceLayer({ node }) === "dialog-popover") {
|
|
3233
|
-
nextDialogPopoverNodeIDs.push(nodeID);
|
|
3234
|
-
} else {
|
|
3235
|
-
nextDefaultNodeIDs.push(nodeID);
|
|
3236
|
-
}
|
|
3237
|
-
}
|
|
3238
|
-
return {
|
|
3239
|
-
defaultNodeIDs: nextDefaultNodeIDs,
|
|
3240
|
-
dialogPopoverNodeIDs: nextDialogPopoverNodeIDs
|
|
3241
|
-
};
|
|
3242
|
-
});
|
|
3243
3304
|
const snapPreviewRect = useWorkbenchSelector(selectWorkbenchSnapPreviewRect);
|
|
3244
3305
|
const presentationInteraction = interactive && presentation?.mode === "mission-control" ? presentation.interaction ?? null : null;
|
|
3245
3306
|
const dialogPopoverLayer = dialogPopoverNodeIDs.length > 0 ? /* @__PURE__ */ jsx8(
|
|
3246
|
-
|
|
3307
|
+
MemoizedWorkbenchNodeLayerGroup,
|
|
3247
3308
|
{
|
|
3248
3309
|
className: "workbench-node-layer workbench-node-layer--dialog-popover",
|
|
3249
3310
|
edgeSnapEnabled,
|
|
3250
3311
|
fullscreenHeaderMode: resolveFullscreenHeaderMode,
|
|
3251
|
-
genie,
|
|
3312
|
+
genieNodeVisibility: genie.nodeVisibility,
|
|
3252
3313
|
interactive,
|
|
3314
|
+
minimizeNodeToAnchor: genie.minimizeNodeToAnchor,
|
|
3253
3315
|
nodeIDs: dialogPopoverNodeIDs,
|
|
3254
3316
|
presentation,
|
|
3255
3317
|
renderNode,
|
|
@@ -3263,13 +3325,14 @@ function WorkbenchNodeLayer({
|
|
|
3263
3325
|
) : null;
|
|
3264
3326
|
return /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
3265
3327
|
/* @__PURE__ */ jsx8(
|
|
3266
|
-
|
|
3328
|
+
MemoizedWorkbenchNodeLayerGroup,
|
|
3267
3329
|
{
|
|
3268
3330
|
className: "workbench-node-layer",
|
|
3269
3331
|
edgeSnapEnabled,
|
|
3270
3332
|
fullscreenHeaderMode: resolveFullscreenHeaderMode,
|
|
3271
|
-
genie,
|
|
3333
|
+
genieNodeVisibility: genie.nodeVisibility,
|
|
3272
3334
|
interactive,
|
|
3335
|
+
minimizeNodeToAnchor: genie.minimizeNodeToAnchor,
|
|
3273
3336
|
nodeIDs: defaultNodeIDs,
|
|
3274
3337
|
onBackdropPress: presentationInteraction?.onBackdropPress,
|
|
3275
3338
|
presentation,
|
|
@@ -3290,8 +3353,9 @@ function WorkbenchNodeLayerGroup({
|
|
|
3290
3353
|
className,
|
|
3291
3354
|
edgeSnapEnabled,
|
|
3292
3355
|
fullscreenHeaderMode,
|
|
3293
|
-
|
|
3356
|
+
genieNodeVisibility,
|
|
3294
3357
|
interactive,
|
|
3358
|
+
minimizeNodeToAnchor,
|
|
3295
3359
|
nodeIDs,
|
|
3296
3360
|
onBackdropPress,
|
|
3297
3361
|
presentation,
|
|
@@ -3332,9 +3396,10 @@ function WorkbenchNodeLayerGroup({
|
|
|
3332
3396
|
MemoizedWorkbenchNodeLayerItem,
|
|
3333
3397
|
{
|
|
3334
3398
|
fullscreenHeaderMode,
|
|
3335
|
-
|
|
3399
|
+
genieNodeVisibility,
|
|
3336
3400
|
edgeSnapEnabled,
|
|
3337
3401
|
interactive,
|
|
3402
|
+
minimizeNodeToAnchor,
|
|
3338
3403
|
nodeID,
|
|
3339
3404
|
presentation,
|
|
3340
3405
|
renderNode,
|
|
@@ -3351,11 +3416,15 @@ function WorkbenchNodeLayerGroup({
|
|
|
3351
3416
|
}
|
|
3352
3417
|
);
|
|
3353
3418
|
}
|
|
3419
|
+
var MemoizedWorkbenchNodeLayerGroup = memo(
|
|
3420
|
+
WorkbenchNodeLayerGroup
|
|
3421
|
+
);
|
|
3354
3422
|
function WorkbenchNodeLayerItem({
|
|
3355
3423
|
fullscreenHeaderMode,
|
|
3356
|
-
|
|
3424
|
+
genieNodeVisibility,
|
|
3357
3425
|
edgeSnapEnabled,
|
|
3358
3426
|
interactive,
|
|
3427
|
+
minimizeNodeToAnchor,
|
|
3359
3428
|
nodeID,
|
|
3360
3429
|
presentation,
|
|
3361
3430
|
renderNode,
|
|
@@ -3393,7 +3462,8 @@ function WorkbenchNodeLayerItem({
|
|
|
3393
3462
|
interactive,
|
|
3394
3463
|
presentation,
|
|
3395
3464
|
node,
|
|
3396
|
-
|
|
3465
|
+
genieNodeVisibility,
|
|
3466
|
+
minimizeNodeToAnchor,
|
|
3397
3467
|
resolveWindowZIndex,
|
|
3398
3468
|
fullscreenHeaderMode: fullscreenHeaderMode?.({
|
|
3399
3469
|
controller,
|
|
@@ -3612,6 +3682,10 @@ var genieVerticalRowStagger = 0.2;
|
|
|
3612
3682
|
var genieDockGlowRadius = 55;
|
|
3613
3683
|
var genieScanlineStrideThresholdPx = 640;
|
|
3614
3684
|
var genieMaxScanlineStride = 3;
|
|
3685
|
+
var genieWarmupTextureWidthRatio = 0.65;
|
|
3686
|
+
var genieWarmupTextureHeightRatio = 0.7;
|
|
3687
|
+
var genieWarmupTextureMaxWidth = 1280;
|
|
3688
|
+
var genieWarmupTextureMaxHeight = 800;
|
|
3615
3689
|
function clampGenieProgress(value) {
|
|
3616
3690
|
return Math.max(0, Math.min(1, value));
|
|
3617
3691
|
}
|
|
@@ -3642,6 +3716,9 @@ function viewportRectFromElement(element) {
|
|
|
3642
3716
|
function isUsableGenieRect(rect) {
|
|
3643
3717
|
return rect.width > 0 && rect.height > 0;
|
|
3644
3718
|
}
|
|
3719
|
+
function isGenieTextureResolutionSufficient(source, target) {
|
|
3720
|
+
return Number.isFinite(source.width) && Number.isFinite(source.height) && source.width >= Math.max(1, Math.round(target.width)) && source.height >= Math.max(1, Math.round(target.height));
|
|
3721
|
+
}
|
|
3645
3722
|
function centerPointFromRect(rect) {
|
|
3646
3723
|
return {
|
|
3647
3724
|
x: rect.left + rect.width / 2,
|
|
@@ -3818,9 +3895,117 @@ function renderGenieScanlines(context, viewportWidth, viewportHeight, frame) {
|
|
|
3818
3895
|
dirtyRect.height
|
|
3819
3896
|
);
|
|
3820
3897
|
}
|
|
3898
|
+
function resolveGenieWarmupTextureSize(viewportWidth, viewportHeight) {
|
|
3899
|
+
return {
|
|
3900
|
+
height: Math.max(
|
|
3901
|
+
1,
|
|
3902
|
+
Math.min(
|
|
3903
|
+
genieWarmupTextureMaxHeight,
|
|
3904
|
+
Math.round(viewportHeight * genieWarmupTextureHeightRatio)
|
|
3905
|
+
)
|
|
3906
|
+
),
|
|
3907
|
+
width: Math.max(
|
|
3908
|
+
1,
|
|
3909
|
+
Math.min(
|
|
3910
|
+
genieWarmupTextureMaxWidth,
|
|
3911
|
+
Math.round(viewportWidth * genieWarmupTextureWidthRatio)
|
|
3912
|
+
)
|
|
3913
|
+
)
|
|
3914
|
+
};
|
|
3915
|
+
}
|
|
3916
|
+
function renderGenieWarmupFrames(context, viewportWidth, viewportHeight, texture) {
|
|
3917
|
+
const textureRect = {
|
|
3918
|
+
height: texture.height,
|
|
3919
|
+
left: (viewportWidth - texture.width) / 2,
|
|
3920
|
+
top: (viewportHeight - texture.height) / 2,
|
|
3921
|
+
width: texture.width
|
|
3922
|
+
};
|
|
3923
|
+
const dockPoint = {
|
|
3924
|
+
x: viewportWidth / 2,
|
|
3925
|
+
y: Math.max(0, viewportHeight - 24)
|
|
3926
|
+
};
|
|
3927
|
+
renderGenieScanlines(context, viewportWidth, viewportHeight, {
|
|
3928
|
+
direction: "minimize",
|
|
3929
|
+
dockPoint,
|
|
3930
|
+
progress: 0,
|
|
3931
|
+
texture,
|
|
3932
|
+
textureRect
|
|
3933
|
+
});
|
|
3934
|
+
renderGenieScanlines(context, viewportWidth, viewportHeight, {
|
|
3935
|
+
direction: "minimize",
|
|
3936
|
+
dockPoint,
|
|
3937
|
+
progress: 0.5,
|
|
3938
|
+
texture,
|
|
3939
|
+
textureRect
|
|
3940
|
+
});
|
|
3941
|
+
renderGenieScanlines(context, viewportWidth, viewportHeight, {
|
|
3942
|
+
direction: "open",
|
|
3943
|
+
dockPoint,
|
|
3944
|
+
progress: 0,
|
|
3945
|
+
texture,
|
|
3946
|
+
textureRect
|
|
3947
|
+
});
|
|
3948
|
+
context.clearRect(0, 0, viewportWidth, viewportHeight);
|
|
3949
|
+
}
|
|
3821
3950
|
|
|
3822
3951
|
// src/react/genieTextureCapture.ts
|
|
3952
|
+
var genieCloneMaskImageProperties = [
|
|
3953
|
+
"-webkit-mask-image",
|
|
3954
|
+
"mask-image"
|
|
3955
|
+
];
|
|
3823
3956
|
var readableStylesheetTextByDocument = /* @__PURE__ */ new WeakMap();
|
|
3957
|
+
function readSingleCssUrl(value) {
|
|
3958
|
+
const normalized = value.trim();
|
|
3959
|
+
if (!normalized.startsWith("url(") || !normalized.endsWith(")")) {
|
|
3960
|
+
return null;
|
|
3961
|
+
}
|
|
3962
|
+
const inner = normalized.slice(4, -1).trim();
|
|
3963
|
+
if (!inner) {
|
|
3964
|
+
return null;
|
|
3965
|
+
}
|
|
3966
|
+
const quote = inner[0];
|
|
3967
|
+
if (quote === '"' || quote === "'") {
|
|
3968
|
+
return inner.endsWith(quote) ? inner.slice(1, -1) : null;
|
|
3969
|
+
}
|
|
3970
|
+
return inner.includes('"') || inner.includes("'") ? null : inner;
|
|
3971
|
+
}
|
|
3972
|
+
async function inlineGenieCloneMaskImageResources({
|
|
3973
|
+
cloneRoot,
|
|
3974
|
+
readResource
|
|
3975
|
+
}) {
|
|
3976
|
+
const referencesByUrl = /* @__PURE__ */ new Map();
|
|
3977
|
+
const elements = [
|
|
3978
|
+
cloneRoot,
|
|
3979
|
+
...Array.from(cloneRoot.querySelectorAll("[style]"))
|
|
3980
|
+
];
|
|
3981
|
+
for (const element of elements) {
|
|
3982
|
+
for (const property of genieCloneMaskImageProperties) {
|
|
3983
|
+
const url = readSingleCssUrl(element.style.getPropertyValue(property));
|
|
3984
|
+
if (!url) {
|
|
3985
|
+
continue;
|
|
3986
|
+
}
|
|
3987
|
+
const references = referencesByUrl.get(url) ?? [];
|
|
3988
|
+
references.push({ element, property });
|
|
3989
|
+
referencesByUrl.set(url, references);
|
|
3990
|
+
}
|
|
3991
|
+
}
|
|
3992
|
+
await Promise.all(
|
|
3993
|
+
Array.from(referencesByUrl.entries(), async ([url, references], index) => {
|
|
3994
|
+
const inlineUrl = await readResource(url);
|
|
3995
|
+
if (!inlineUrl) {
|
|
3996
|
+
return;
|
|
3997
|
+
}
|
|
3998
|
+
const variableName = `--workbench-genie-capture-mask-${index}`;
|
|
3999
|
+
cloneRoot.style.setProperty(
|
|
4000
|
+
variableName,
|
|
4001
|
+
`url(${JSON.stringify(inlineUrl)})`
|
|
4002
|
+
);
|
|
4003
|
+
for (const { element, property } of references) {
|
|
4004
|
+
element.style.setProperty(property, `var(${variableName})`);
|
|
4005
|
+
}
|
|
4006
|
+
})
|
|
4007
|
+
);
|
|
4008
|
+
}
|
|
3824
4009
|
function hasSameStylesheetFingerprints(left, right) {
|
|
3825
4010
|
return left.length === right.length && left.every((fingerprint, index) => {
|
|
3826
4011
|
const candidate = right[index];
|
|
@@ -3947,6 +4132,224 @@ function prepareGenieTextureCapture(element) {
|
|
|
3947
4132
|
};
|
|
3948
4133
|
}
|
|
3949
4134
|
|
|
4135
|
+
// src/react/genieTextureCache.ts
|
|
4136
|
+
function readWorkbenchGenieTextureCacheEntry(cache, nodeID) {
|
|
4137
|
+
const value = cache.get(nodeID) ?? null;
|
|
4138
|
+
if (!value) {
|
|
4139
|
+
return null;
|
|
4140
|
+
}
|
|
4141
|
+
cache.delete(nodeID);
|
|
4142
|
+
cache.set(nodeID, value);
|
|
4143
|
+
return value;
|
|
4144
|
+
}
|
|
4145
|
+
function writeWorkbenchGenieTextureCacheEntry(cache, nodeID, value, limits) {
|
|
4146
|
+
cache.delete(nodeID);
|
|
4147
|
+
cache.set(nodeID, value);
|
|
4148
|
+
pruneWorkbenchGenieTextureCache(cache, limits);
|
|
4149
|
+
}
|
|
4150
|
+
function estimateWorkbenchGenieTextureBytes(value) {
|
|
4151
|
+
return Math.max(0, value.canvas.width) * Math.max(0, value.canvas.height) * 4;
|
|
4152
|
+
}
|
|
4153
|
+
function pruneRemovedWorkbenchGenieTextureCacheEntries(cache, existingNodeIDs) {
|
|
4154
|
+
for (const nodeID of cache.keys()) {
|
|
4155
|
+
if (!existingNodeIDs.has(nodeID)) {
|
|
4156
|
+
cache.delete(nodeID);
|
|
4157
|
+
}
|
|
4158
|
+
}
|
|
4159
|
+
}
|
|
4160
|
+
function pruneWorkbenchGenieTextureCache(cache, limits) {
|
|
4161
|
+
let estimatedBytes = 0;
|
|
4162
|
+
for (const value of cache.values()) {
|
|
4163
|
+
estimatedBytes += estimateWorkbenchGenieTextureBytes(value);
|
|
4164
|
+
}
|
|
4165
|
+
while (cache.size > limits.maxEntries || estimatedBytes > limits.maxBytes) {
|
|
4166
|
+
const oldest = cache.entries().next().value;
|
|
4167
|
+
if (!oldest) {
|
|
4168
|
+
return;
|
|
4169
|
+
}
|
|
4170
|
+
cache.delete(oldest[0]);
|
|
4171
|
+
estimatedBytes -= estimateWorkbenchGenieTextureBytes(oldest[1]);
|
|
4172
|
+
}
|
|
4173
|
+
}
|
|
4174
|
+
|
|
4175
|
+
// src/react/genieNodeVisibility.ts
|
|
4176
|
+
function createWorkbenchGenieNodeVisibilityStore() {
|
|
4177
|
+
const hiddenNodeIDs = /* @__PURE__ */ new Set();
|
|
4178
|
+
const hiddenTokenByNodeID = /* @__PURE__ */ new Map();
|
|
4179
|
+
const listenersByNodeID = /* @__PURE__ */ new Map();
|
|
4180
|
+
const setHidden = (nodeID, hidden) => {
|
|
4181
|
+
if (hiddenNodeIDs.has(nodeID) === hidden) {
|
|
4182
|
+
return;
|
|
4183
|
+
}
|
|
4184
|
+
if (hidden) {
|
|
4185
|
+
hiddenNodeIDs.add(nodeID);
|
|
4186
|
+
} else {
|
|
4187
|
+
hiddenNodeIDs.delete(nodeID);
|
|
4188
|
+
}
|
|
4189
|
+
for (const listener of listenersByNodeID.get(nodeID) ?? []) {
|
|
4190
|
+
listener();
|
|
4191
|
+
}
|
|
4192
|
+
};
|
|
4193
|
+
const hide = (nodeID) => {
|
|
4194
|
+
const token = Symbol(nodeID);
|
|
4195
|
+
hiddenTokenByNodeID.set(nodeID, token);
|
|
4196
|
+
setHidden(nodeID, true);
|
|
4197
|
+
return token;
|
|
4198
|
+
};
|
|
4199
|
+
const show = (nodeID, token) => {
|
|
4200
|
+
if (token && hiddenTokenByNodeID.get(nodeID) !== token) {
|
|
4201
|
+
return false;
|
|
4202
|
+
}
|
|
4203
|
+
hiddenTokenByNodeID.delete(nodeID);
|
|
4204
|
+
setHidden(nodeID, false);
|
|
4205
|
+
return true;
|
|
4206
|
+
};
|
|
4207
|
+
return {
|
|
4208
|
+
dispose() {
|
|
4209
|
+
hiddenNodeIDs.clear();
|
|
4210
|
+
hiddenTokenByNodeID.clear();
|
|
4211
|
+
listenersByNodeID.clear();
|
|
4212
|
+
},
|
|
4213
|
+
getSnapshot(nodeID) {
|
|
4214
|
+
return hiddenNodeIDs.has(nodeID);
|
|
4215
|
+
},
|
|
4216
|
+
hide,
|
|
4217
|
+
setHidden(nodeID, hidden) {
|
|
4218
|
+
if (hidden) {
|
|
4219
|
+
hide(nodeID);
|
|
4220
|
+
} else {
|
|
4221
|
+
show(nodeID);
|
|
4222
|
+
}
|
|
4223
|
+
},
|
|
4224
|
+
show,
|
|
4225
|
+
subscribe(nodeID, listener) {
|
|
4226
|
+
const listeners = listenersByNodeID.get(nodeID) ?? /* @__PURE__ */ new Set();
|
|
4227
|
+
listeners.add(listener);
|
|
4228
|
+
listenersByNodeID.set(nodeID, listeners);
|
|
4229
|
+
return () => {
|
|
4230
|
+
listeners.delete(listener);
|
|
4231
|
+
if (listeners.size === 0) {
|
|
4232
|
+
listenersByNodeID.delete(nodeID);
|
|
4233
|
+
}
|
|
4234
|
+
};
|
|
4235
|
+
}
|
|
4236
|
+
};
|
|
4237
|
+
}
|
|
4238
|
+
|
|
4239
|
+
// src/react/workbenchGenieScheduling.ts
|
|
4240
|
+
function startCachedWorkbenchGenieRestore({
|
|
4241
|
+
launch,
|
|
4242
|
+
onLaunchSettled,
|
|
4243
|
+
scheduleTask,
|
|
4244
|
+
startAnimation
|
|
4245
|
+
}) {
|
|
4246
|
+
let launchScheduled = false;
|
|
4247
|
+
const launchAfterAnimation = () => {
|
|
4248
|
+
if (launchScheduled) {
|
|
4249
|
+
return;
|
|
4250
|
+
}
|
|
4251
|
+
launchScheduled = true;
|
|
4252
|
+
scheduleTask(() => {
|
|
4253
|
+
void Promise.resolve(launch()).then(onLaunchSettled, onLaunchSettled);
|
|
4254
|
+
});
|
|
4255
|
+
};
|
|
4256
|
+
startAnimation(launchAfterAnimation);
|
|
4257
|
+
}
|
|
4258
|
+
function scheduleWorkbenchGenieWarmup({
|
|
4259
|
+
isAnimationActive,
|
|
4260
|
+
isWarmupComplete,
|
|
4261
|
+
renderWarmup,
|
|
4262
|
+
scheduler
|
|
4263
|
+
}) {
|
|
4264
|
+
let cancelled = false;
|
|
4265
|
+
let idleID = null;
|
|
4266
|
+
const schedule = () => {
|
|
4267
|
+
idleID = scheduler.requestIdleCallback(runWarmup);
|
|
4268
|
+
};
|
|
4269
|
+
const runWarmup = () => {
|
|
4270
|
+
idleID = null;
|
|
4271
|
+
if (cancelled || isWarmupComplete()) {
|
|
4272
|
+
return;
|
|
4273
|
+
}
|
|
4274
|
+
if (isAnimationActive()) {
|
|
4275
|
+
schedule();
|
|
4276
|
+
return;
|
|
4277
|
+
}
|
|
4278
|
+
renderWarmup();
|
|
4279
|
+
};
|
|
4280
|
+
schedule();
|
|
4281
|
+
return () => {
|
|
4282
|
+
cancelled = true;
|
|
4283
|
+
if (idleID !== null) {
|
|
4284
|
+
scheduler.cancelIdleCallback(idleID);
|
|
4285
|
+
}
|
|
4286
|
+
};
|
|
4287
|
+
}
|
|
4288
|
+
function scheduleWorkbenchGeniePostAnimationIdleTask({
|
|
4289
|
+
isAnimationActive,
|
|
4290
|
+
isCancelled,
|
|
4291
|
+
runTask,
|
|
4292
|
+
scheduler
|
|
4293
|
+
}) {
|
|
4294
|
+
let cancelled = false;
|
|
4295
|
+
let idleID = null;
|
|
4296
|
+
const schedule = () => {
|
|
4297
|
+
idleID = scheduler.requestIdleCallback(run);
|
|
4298
|
+
};
|
|
4299
|
+
const run = () => {
|
|
4300
|
+
idleID = null;
|
|
4301
|
+
if (cancelled || isCancelled()) {
|
|
4302
|
+
return;
|
|
4303
|
+
}
|
|
4304
|
+
if (isAnimationActive()) {
|
|
4305
|
+
schedule();
|
|
4306
|
+
return;
|
|
4307
|
+
}
|
|
4308
|
+
runTask();
|
|
4309
|
+
};
|
|
4310
|
+
schedule();
|
|
4311
|
+
return () => {
|
|
4312
|
+
cancelled = true;
|
|
4313
|
+
if (idleID !== null) {
|
|
4314
|
+
scheduler.cancelIdleCallback(idleID);
|
|
4315
|
+
}
|
|
4316
|
+
};
|
|
4317
|
+
}
|
|
4318
|
+
async function resolveNativeFirstGenieTexture({
|
|
4319
|
+
nativeImageUrlPromise,
|
|
4320
|
+
renderDomFallback,
|
|
4321
|
+
renderNativeImage,
|
|
4322
|
+
timeoutMs
|
|
4323
|
+
}) {
|
|
4324
|
+
const nativeCapture = await new Promise((resolve) => {
|
|
4325
|
+
let settled = false;
|
|
4326
|
+
const settleResolved = (nativeImageUrl) => {
|
|
4327
|
+
if (settled) {
|
|
4328
|
+
return;
|
|
4329
|
+
}
|
|
4330
|
+
settled = true;
|
|
4331
|
+
clearTimeout(timer);
|
|
4332
|
+
resolve({ nativeImageUrl, nativeStatus: "resolved" });
|
|
4333
|
+
};
|
|
4334
|
+
const timer = setTimeout(() => {
|
|
4335
|
+
if (settled) {
|
|
4336
|
+
return;
|
|
4337
|
+
}
|
|
4338
|
+
settled = true;
|
|
4339
|
+
resolve({ nativeImageUrl: null, nativeStatus: "pending" });
|
|
4340
|
+
}, timeoutMs);
|
|
4341
|
+
nativeImageUrlPromise.then(settleResolved, () => settleResolved(null));
|
|
4342
|
+
});
|
|
4343
|
+
const nativeTexture = nativeCapture.nativeImageUrl ? await Promise.resolve(
|
|
4344
|
+
renderNativeImage(nativeCapture.nativeImageUrl)
|
|
4345
|
+
).catch(() => null) : null;
|
|
4346
|
+
const texture = nativeTexture ?? await Promise.resolve(renderDomFallback()).catch(() => null);
|
|
4347
|
+
return {
|
|
4348
|
+
...nativeCapture,
|
|
4349
|
+
texture
|
|
4350
|
+
};
|
|
4351
|
+
}
|
|
4352
|
+
|
|
3950
4353
|
// src/react/useWorkbenchGenieAnimation.tsx
|
|
3951
4354
|
import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
3952
4355
|
var genieDurationMs = 400;
|
|
@@ -3960,6 +4363,8 @@ var dockAnchorResolveMaxAnimationFrames = 3;
|
|
|
3960
4363
|
var dockPreviewMaxWidth = 260;
|
|
3961
4364
|
var dockPreviewMaxHeight = 170;
|
|
3962
4365
|
var dockPreviewImageCacheMaxEntries = 96;
|
|
4366
|
+
var minimizedGenieTextureCacheMaxBytes = 64 * 1024 * 1024;
|
|
4367
|
+
var minimizedGenieTextureCacheMaxEntries = 8;
|
|
3963
4368
|
var inlineImageResourceCacheMaxEntries = 160;
|
|
3964
4369
|
var inlineImageResizeTargetCacheMaxEntries = 4;
|
|
3965
4370
|
var dockAnchorFallbackSizePx = 43.2;
|
|
@@ -3977,26 +4382,6 @@ function waitForNextAnimationFrame() {
|
|
|
3977
4382
|
window.requestAnimationFrame(() => resolve());
|
|
3978
4383
|
});
|
|
3979
4384
|
}
|
|
3980
|
-
function racePreviewImageCapture(promise, timeoutMs) {
|
|
3981
|
-
return new Promise((resolve) => {
|
|
3982
|
-
let settled = false;
|
|
3983
|
-
const timer = setTimeout(() => {
|
|
3984
|
-
if (settled) {
|
|
3985
|
-
return;
|
|
3986
|
-
}
|
|
3987
|
-
settled = true;
|
|
3988
|
-
resolve({ previewImageUrl: null, status: "pending" });
|
|
3989
|
-
}, timeoutMs);
|
|
3990
|
-
promise.then((previewImageUrl) => {
|
|
3991
|
-
if (settled) {
|
|
3992
|
-
return;
|
|
3993
|
-
}
|
|
3994
|
-
settled = true;
|
|
3995
|
-
clearTimeout(timer);
|
|
3996
|
-
resolve({ previewImageUrl, status: "resolved" });
|
|
3997
|
-
});
|
|
3998
|
-
});
|
|
3999
|
-
}
|
|
4000
4385
|
function isFocusedWorkbenchNode(controller, nodeID) {
|
|
4001
4386
|
return controller.getSnapshot().nodeStack.at(-1) === nodeID;
|
|
4002
4387
|
}
|
|
@@ -4094,8 +4479,12 @@ async function inlineCloneImageResources({
|
|
|
4094
4479
|
images
|
|
4095
4480
|
}) {
|
|
4096
4481
|
const cloneImages = Array.from(cloneRoot.querySelectorAll("img"));
|
|
4097
|
-
await Promise.all(
|
|
4098
|
-
|
|
4482
|
+
await Promise.all([
|
|
4483
|
+
inlineGenieCloneMaskImageResources({
|
|
4484
|
+
cloneRoot,
|
|
4485
|
+
readResource: readInlineImageResource
|
|
4486
|
+
}),
|
|
4487
|
+
...images.map(async (imageInfo, index) => {
|
|
4099
4488
|
const cloneImage = cloneImages[index];
|
|
4100
4489
|
if (!cloneImage) {
|
|
4101
4490
|
return;
|
|
@@ -4118,7 +4507,7 @@ async function inlineCloneImageResources({
|
|
|
4118
4507
|
}
|
|
4119
4508
|
cloneImage.src = inlineImageUrl;
|
|
4120
4509
|
})
|
|
4121
|
-
);
|
|
4510
|
+
]);
|
|
4122
4511
|
}
|
|
4123
4512
|
async function loadImageFromSvg(svg) {
|
|
4124
4513
|
const image = new Image();
|
|
@@ -4293,6 +4682,12 @@ async function renderPreviewImageTexture({
|
|
|
4293
4682
|
const image = new Image();
|
|
4294
4683
|
image.src = previewImageUrl;
|
|
4295
4684
|
await image.decode();
|
|
4685
|
+
if (!isGenieTextureResolutionSufficient(
|
|
4686
|
+
{ height: image.naturalHeight, width: image.naturalWidth },
|
|
4687
|
+
rect
|
|
4688
|
+
)) {
|
|
4689
|
+
return null;
|
|
4690
|
+
}
|
|
4296
4691
|
const canvas = document.createElement("canvas");
|
|
4297
4692
|
canvas.width = Math.max(1, Math.round(rect.width * genieSnapshotScale));
|
|
4298
4693
|
canvas.height = Math.max(1, Math.round(rect.height * genieSnapshotScale));
|
|
@@ -4415,6 +4810,7 @@ function createGenieSvgTexture(element, rect, outputSize = {
|
|
|
4415
4810
|
}
|
|
4416
4811
|
function useWorkbenchGenieAnimation({
|
|
4417
4812
|
captureNodePreviewImage,
|
|
4813
|
+
captureNodePreviewImages,
|
|
4418
4814
|
controller,
|
|
4419
4815
|
debugDiagnostics,
|
|
4420
4816
|
dockPreviewCache,
|
|
@@ -4427,6 +4823,7 @@ function useWorkbenchGenieAnimation({
|
|
|
4427
4823
|
const dockAnchorElementsRef = useRef5(/* @__PURE__ */ new Map());
|
|
4428
4824
|
const canvasRef = useRef5(null);
|
|
4429
4825
|
const rafRef = useRef5(null);
|
|
4826
|
+
const isMountedRef = useRef5(true);
|
|
4430
4827
|
const animationGenerationRef = useRef5(0);
|
|
4431
4828
|
const animationCleanupRef = useRef5(null);
|
|
4432
4829
|
const minimizedDockEnterAnimationNodeIdsRef = useRef5(/* @__PURE__ */ new Set());
|
|
@@ -4436,13 +4833,14 @@ function useWorkbenchGenieAnimation({
|
|
|
4436
4833
|
const minimizedGenieTextureByNodeIDRef = useRef5(
|
|
4437
4834
|
/* @__PURE__ */ new Map()
|
|
4438
4835
|
);
|
|
4836
|
+
const genieCanvasWarmupCompletedRef = useRef5(false);
|
|
4439
4837
|
const renderedPreviewCaptureIDRef = useRef5(0);
|
|
4440
4838
|
const renderedPreviewCaptureElementRef = useRef5(null);
|
|
4441
4839
|
const pendingRenderedPreviewCaptureRef = useRef5(null);
|
|
4840
|
+
const nodeVisibilityStoreRef = useRef5(null);
|
|
4841
|
+
nodeVisibilityStoreRef.current ??= createWorkbenchGenieNodeVisibilityStore();
|
|
4842
|
+
const nodeVisibility = nodeVisibilityStoreRef.current;
|
|
4442
4843
|
const [isCanvasActive, setIsCanvasActive] = useState4(false);
|
|
4443
|
-
const [genieHiddenNodeIDs, setGenieHiddenNodeIDs] = useState4(
|
|
4444
|
-
() => /* @__PURE__ */ new Set()
|
|
4445
|
-
);
|
|
4446
4844
|
const [pendingMinimizedNode, setPendingMinimizedNode] = useState4(null);
|
|
4447
4845
|
const [pendingRenderedPreviewCapture, setPendingRenderedPreviewCapture] = useState4(null);
|
|
4448
4846
|
const registerDockAnchor = useCallback7(
|
|
@@ -4520,53 +4918,49 @@ function useWorkbenchGenieAnimation({
|
|
|
4520
4918
|
return minimizedDockEnterAnimationNodeIdsRef.current.has(nodeID);
|
|
4521
4919
|
}, []);
|
|
4522
4920
|
const readMinimizedGenieTexture = useCallback7((nodeID) => {
|
|
4523
|
-
return
|
|
4921
|
+
return readWorkbenchGenieTextureCacheEntry(
|
|
4922
|
+
minimizedGenieTextureByNodeIDRef.current,
|
|
4923
|
+
nodeID
|
|
4924
|
+
);
|
|
4524
4925
|
}, []);
|
|
4525
4926
|
const writeMinimizedGenieTexture = useCallback7(
|
|
4526
4927
|
(nodeID, texture) => {
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4928
|
+
writeWorkbenchGenieTextureCacheEntry(
|
|
4929
|
+
minimizedGenieTextureByNodeIDRef.current,
|
|
4930
|
+
nodeID,
|
|
4931
|
+
texture,
|
|
4932
|
+
{
|
|
4933
|
+
maxBytes: minimizedGenieTextureCacheMaxBytes,
|
|
4934
|
+
maxEntries: minimizedGenieTextureCacheMaxEntries
|
|
4935
|
+
}
|
|
4936
|
+
);
|
|
4530
4937
|
},
|
|
4531
4938
|
[]
|
|
4532
4939
|
);
|
|
4533
4940
|
const clearMinimizedGenieTexture = useCallback7((nodeID) => {
|
|
4534
4941
|
minimizedGenieTextureByNodeIDRef.current.delete(nodeID);
|
|
4535
4942
|
}, []);
|
|
4536
|
-
const
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
}
|
|
4943
|
+
const pruneRemovedNodeGenieTextures = useCallback7(() => {
|
|
4944
|
+
const existingNodeIDs = new Set(
|
|
4945
|
+
controller.getSnapshot().nodes.map((node) => node.id)
|
|
4946
|
+
);
|
|
4947
|
+
pruneRemovedWorkbenchGenieTextureCacheEntries(
|
|
4948
|
+
minimizedGenieTextureByNodeIDRef.current,
|
|
4949
|
+
existingNodeIDs
|
|
4950
|
+
);
|
|
4951
|
+
}, [controller]);
|
|
4952
|
+
const hideNodeForGenie = useCallback7(
|
|
4953
|
+
(nodeID) => {
|
|
4954
|
+
return nodeVisibility.hide(nodeID);
|
|
4549
4955
|
},
|
|
4550
|
-
[
|
|
4956
|
+
[nodeVisibility]
|
|
4957
|
+
);
|
|
4958
|
+
const showNodeForGenie = useCallback7(
|
|
4959
|
+
(nodeID, token) => {
|
|
4960
|
+
return nodeVisibility.show(nodeID, token);
|
|
4961
|
+
},
|
|
4962
|
+
[nodeVisibility]
|
|
4551
4963
|
);
|
|
4552
|
-
const hideNodeForGenie = useCallback7((nodeID) => {
|
|
4553
|
-
setGenieHiddenNodeIDs((current) => {
|
|
4554
|
-
if (current.has(nodeID)) {
|
|
4555
|
-
return current;
|
|
4556
|
-
}
|
|
4557
|
-
return /* @__PURE__ */ new Set([...current, nodeID]);
|
|
4558
|
-
});
|
|
4559
|
-
}, []);
|
|
4560
|
-
const showNodeForGenie = useCallback7((nodeID) => {
|
|
4561
|
-
setGenieHiddenNodeIDs((current) => {
|
|
4562
|
-
if (!current.has(nodeID)) {
|
|
4563
|
-
return current;
|
|
4564
|
-
}
|
|
4565
|
-
const next = new Set(current);
|
|
4566
|
-
next.delete(nodeID);
|
|
4567
|
-
return next;
|
|
4568
|
-
});
|
|
4569
|
-
}, []);
|
|
4570
4964
|
const clearPendingMinimizedNode = useCallback7((nodeID) => {
|
|
4571
4965
|
setPendingMinimizedNode(
|
|
4572
4966
|
(current) => current?.id === nodeID ? null : current
|
|
@@ -4658,8 +5052,20 @@ function useWorkbenchGenieAnimation({
|
|
|
4658
5052
|
);
|
|
4659
5053
|
const viewportWidth = window.innerWidth;
|
|
4660
5054
|
const viewportHeight = window.innerHeight;
|
|
4661
|
-
|
|
4662
|
-
|
|
5055
|
+
const pixelWidth = Math.max(
|
|
5056
|
+
1,
|
|
5057
|
+
Math.round(viewportWidth * devicePixelRatio)
|
|
5058
|
+
);
|
|
5059
|
+
const pixelHeight = Math.max(
|
|
5060
|
+
1,
|
|
5061
|
+
Math.round(viewportHeight * devicePixelRatio)
|
|
5062
|
+
);
|
|
5063
|
+
if (canvas.width !== pixelWidth) {
|
|
5064
|
+
canvas.width = pixelWidth;
|
|
5065
|
+
}
|
|
5066
|
+
if (canvas.height !== pixelHeight) {
|
|
5067
|
+
canvas.height = pixelHeight;
|
|
5068
|
+
}
|
|
4663
5069
|
canvas.style.width = `${viewportWidth}px`;
|
|
4664
5070
|
canvas.style.height = `${viewportHeight}px`;
|
|
4665
5071
|
const context = canvas.getContext("2d");
|
|
@@ -4669,6 +5075,48 @@ function useWorkbenchGenieAnimation({
|
|
|
4669
5075
|
context.setTransform(devicePixelRatio, 0, 0, devicePixelRatio, 0, 0);
|
|
4670
5076
|
return { context, viewportHeight, viewportWidth };
|
|
4671
5077
|
}, []);
|
|
5078
|
+
useEffect4(() => {
|
|
5079
|
+
if (minimizeAnimation !== "genie" || shouldReduceMotion() || typeof window.requestIdleCallback !== "function") {
|
|
5080
|
+
return;
|
|
5081
|
+
}
|
|
5082
|
+
return scheduleWorkbenchGenieWarmup({
|
|
5083
|
+
isAnimationActive: () => rafRef.current !== null,
|
|
5084
|
+
isWarmupComplete: () => !isMountedRef.current || genieCanvasWarmupCompletedRef.current,
|
|
5085
|
+
renderWarmup: function warmGenieCanvas() {
|
|
5086
|
+
const setup = setupCanvas();
|
|
5087
|
+
if (!setup) {
|
|
5088
|
+
return;
|
|
5089
|
+
}
|
|
5090
|
+
const warmupSize = resolveGenieWarmupTextureSize(
|
|
5091
|
+
setup.viewportWidth,
|
|
5092
|
+
setup.viewportHeight
|
|
5093
|
+
);
|
|
5094
|
+
const warmupTexture = document.createElement("canvas");
|
|
5095
|
+
warmupTexture.width = warmupSize.width;
|
|
5096
|
+
warmupTexture.height = warmupSize.height;
|
|
5097
|
+
const warmupContext = warmupTexture.getContext("2d");
|
|
5098
|
+
warmupContext?.fillRect(
|
|
5099
|
+
0,
|
|
5100
|
+
0,
|
|
5101
|
+
warmupTexture.width,
|
|
5102
|
+
warmupTexture.height
|
|
5103
|
+
);
|
|
5104
|
+
renderGenieWarmupFrames(
|
|
5105
|
+
setup.context,
|
|
5106
|
+
setup.viewportWidth,
|
|
5107
|
+
setup.viewportHeight,
|
|
5108
|
+
warmupTexture
|
|
5109
|
+
);
|
|
5110
|
+
genieCanvasWarmupCompletedRef.current = true;
|
|
5111
|
+
},
|
|
5112
|
+
scheduler: {
|
|
5113
|
+
cancelIdleCallback: (idleID) => {
|
|
5114
|
+
window.cancelIdleCallback(idleID);
|
|
5115
|
+
},
|
|
5116
|
+
requestIdleCallback: (callback) => window.requestIdleCallback(callback)
|
|
5117
|
+
}
|
|
5118
|
+
});
|
|
5119
|
+
}, [minimizeAnimation, setupCanvas]);
|
|
4672
5120
|
const clearCanvas = useCallback7(() => {
|
|
4673
5121
|
const canvas = canvasRef.current;
|
|
4674
5122
|
const context = canvas?.getContext("2d") ?? null;
|
|
@@ -4989,7 +5437,52 @@ function useWorkbenchGenieAnimation({
|
|
|
4989
5437
|
}
|
|
4990
5438
|
stopAnimation();
|
|
4991
5439
|
const dockRectFallback = resolveDockAnchorRect(anchorKey);
|
|
4992
|
-
|
|
5440
|
+
let visibilityToken = null;
|
|
5441
|
+
flushSync(() => {
|
|
5442
|
+
visibilityToken = hideNodeForGenie(nodeID);
|
|
5443
|
+
});
|
|
5444
|
+
let launchPromise = null;
|
|
5445
|
+
const launchOnce = () => {
|
|
5446
|
+
if (!isMountedRef.current) {
|
|
5447
|
+
return Promise.resolve(null);
|
|
5448
|
+
}
|
|
5449
|
+
launchPromise ??= Promise.resolve(launch()).catch(() => null);
|
|
5450
|
+
return launchPromise;
|
|
5451
|
+
};
|
|
5452
|
+
const cachedTexture = readMinimizedGenieTexture(nodeID);
|
|
5453
|
+
if (effectiveMinimizeAnimation === "genie" && cachedTexture && dockRectFallback && isUsableGenieRect(dockRectFallback)) {
|
|
5454
|
+
const generation2 = animationGenerationRef.current;
|
|
5455
|
+
const revealLaunchedNode = () => {
|
|
5456
|
+
const settledVisibilityToken = visibilityToken;
|
|
5457
|
+
if (!isMountedRef.current || !settledVisibilityToken) {
|
|
5458
|
+
return;
|
|
5459
|
+
}
|
|
5460
|
+
flushSync(() => {
|
|
5461
|
+
showNodeForGenie(nodeID, settledVisibilityToken);
|
|
5462
|
+
});
|
|
5463
|
+
if (generation2 === animationGenerationRef.current) {
|
|
5464
|
+
clearCanvas();
|
|
5465
|
+
}
|
|
5466
|
+
};
|
|
5467
|
+
startCachedWorkbenchGenieRestore({
|
|
5468
|
+
launch: launchOnce,
|
|
5469
|
+
onLaunchSettled: revealLaunchedNode,
|
|
5470
|
+
scheduleTask: (callback) => {
|
|
5471
|
+
window.setTimeout(callback, 0);
|
|
5472
|
+
},
|
|
5473
|
+
startAnimation: (onAnimationSettled) => {
|
|
5474
|
+
runGenieAnimation({
|
|
5475
|
+
direction: "open",
|
|
5476
|
+
dockRect: dockRectFallback,
|
|
5477
|
+
onCancel: onAnimationSettled,
|
|
5478
|
+
onComplete: onAnimationSettled,
|
|
5479
|
+
skipStop: true,
|
|
5480
|
+
texture: cachedTexture
|
|
5481
|
+
});
|
|
5482
|
+
}
|
|
5483
|
+
});
|
|
5484
|
+
return;
|
|
5485
|
+
}
|
|
4993
5486
|
animationCleanupRef.current = () => {
|
|
4994
5487
|
if (rafRef.current !== null) {
|
|
4995
5488
|
window.cancelAnimationFrame(rafRef.current);
|
|
@@ -5007,7 +5500,7 @@ function useWorkbenchGenieAnimation({
|
|
|
5007
5500
|
if (generation !== animationGenerationRef.current) {
|
|
5008
5501
|
return;
|
|
5009
5502
|
}
|
|
5010
|
-
void
|
|
5503
|
+
void launchOnce().then(() => {
|
|
5011
5504
|
if (generation !== animationGenerationRef.current) {
|
|
5012
5505
|
return;
|
|
5013
5506
|
}
|
|
@@ -5027,7 +5520,9 @@ function useWorkbenchGenieAnimation({
|
|
|
5027
5520
|
controller,
|
|
5028
5521
|
hideNodeForGenie,
|
|
5029
5522
|
minimizeAnimation,
|
|
5523
|
+
readMinimizedGenieTexture,
|
|
5030
5524
|
resolveDockAnchorRect,
|
|
5525
|
+
runGenieAnimation,
|
|
5031
5526
|
showNodeForGenie,
|
|
5032
5527
|
startOpenOrRestoreAnimation,
|
|
5033
5528
|
stopAnimation
|
|
@@ -5036,9 +5531,9 @@ function useWorkbenchGenieAnimation({
|
|
|
5036
5531
|
const minimizeNodeToAnchor = useCallback7(
|
|
5037
5532
|
(nodeID, minimize) => {
|
|
5038
5533
|
void (async () => {
|
|
5039
|
-
pruneMinimizedGenieTextures();
|
|
5040
5534
|
const target = controller.getSnapshot().nodes.find((node) => node.id === nodeID);
|
|
5041
5535
|
if (!target) {
|
|
5536
|
+
pruneRemovedNodeGenieTextures();
|
|
5042
5537
|
logWorkbenchGenieDiagnostic(
|
|
5043
5538
|
debugDiagnostics,
|
|
5044
5539
|
"workbench.genie.minimize.skipped",
|
|
@@ -5050,9 +5545,12 @@ function useWorkbenchGenieAnimation({
|
|
|
5050
5545
|
);
|
|
5051
5546
|
return;
|
|
5052
5547
|
}
|
|
5053
|
-
|
|
5548
|
+
pruneRemovedNodeGenieTextures();
|
|
5054
5549
|
const runMinimize = minimize ?? (() => controller.commands.minimizeNode(nodeID));
|
|
5055
5550
|
const effectiveMinimizeAnimation = shouldReduceMotion() ? "off" : minimizeAnimation;
|
|
5551
|
+
if (effectiveMinimizeAnimation !== "genie") {
|
|
5552
|
+
clearMinimizedGenieTexture(nodeID);
|
|
5553
|
+
}
|
|
5056
5554
|
const shouldCapturePreview = shouldCaptureNodePreviewImage?.(target) ?? true;
|
|
5057
5555
|
if (effectiveMinimizeAnimation === "off") {
|
|
5058
5556
|
stopAnimation();
|
|
@@ -5255,14 +5753,16 @@ function useWorkbenchGenieAnimation({
|
|
|
5255
5753
|
isMinimized: true,
|
|
5256
5754
|
minimizedAtUnixMs: Date.now()
|
|
5257
5755
|
};
|
|
5258
|
-
const
|
|
5756
|
+
const cachedTexture = shouldCapturePreview ? readMinimizedGenieTexture(nodeID) : null;
|
|
5757
|
+
const reusableTexture = cachedTexture && isGenieTextureResolutionSufficient(cachedTexture.canvas, windowRect) ? { canvas: cachedTexture.canvas, rect: windowRect } : null;
|
|
5758
|
+
const componentPreviewTexture = reusableTexture || shouldCapturePreview ? null : await requestRenderedGeniePreviewTexture({
|
|
5259
5759
|
node: pendingMinimizedNode2,
|
|
5260
5760
|
textureRect: windowRect
|
|
5261
5761
|
}).catch(() => null);
|
|
5262
5762
|
if (generation !== animationGenerationRef.current) {
|
|
5263
5763
|
return;
|
|
5264
5764
|
}
|
|
5265
|
-
if (!shouldCapturePreview) {
|
|
5765
|
+
if (!reusableTexture && !shouldCapturePreview) {
|
|
5266
5766
|
if (!componentPreviewTexture) {
|
|
5267
5767
|
logWorkbenchGenieDiagnostic(
|
|
5268
5768
|
debugDiagnostics,
|
|
@@ -5280,25 +5780,6 @@ function useWorkbenchGenieAnimation({
|
|
|
5280
5780
|
return;
|
|
5281
5781
|
}
|
|
5282
5782
|
}
|
|
5283
|
-
const captureTarget = resolveWorkbenchCaptureElement(nodeElement);
|
|
5284
|
-
const preparedTexture = shouldCapturePreview ? prepareGenieTextureCapture(captureTarget) : null;
|
|
5285
|
-
if (!preparedTexture) {
|
|
5286
|
-
if (!componentPreviewTexture) {
|
|
5287
|
-
logWorkbenchGenieDiagnostic(
|
|
5288
|
-
debugDiagnostics,
|
|
5289
|
-
"workbench.genie.minimize.skipped",
|
|
5290
|
-
{
|
|
5291
|
-
...describeGenieNode(target),
|
|
5292
|
-
mode: "genie",
|
|
5293
|
-
reason: "prepared_texture_missing",
|
|
5294
|
-
shouldCapturePreview
|
|
5295
|
-
},
|
|
5296
|
-
"warn"
|
|
5297
|
-
);
|
|
5298
|
-
runMinimize();
|
|
5299
|
-
return;
|
|
5300
|
-
}
|
|
5301
|
-
}
|
|
5302
5783
|
const wasFocusedForCapture = isFocusedWorkbenchNode(controller, nodeID);
|
|
5303
5784
|
if (shouldCapturePreview && !wasFocusedForCapture) {
|
|
5304
5785
|
flushSync(() => {
|
|
@@ -5309,43 +5790,96 @@ function useWorkbenchGenieAnimation({
|
|
|
5309
5790
|
return;
|
|
5310
5791
|
}
|
|
5311
5792
|
}
|
|
5312
|
-
const
|
|
5793
|
+
const previewImagesPromise = shouldCapturePreview ? captureNodePreviewImages ? Promise.resolve(captureNodePreviewImages(target)).catch(
|
|
5313
5794
|
() => null
|
|
5314
|
-
) : Promise.resolve(null)
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5795
|
+
) : Promise.resolve(captureNodePreviewImage?.(target) ?? null).then(
|
|
5796
|
+
(previewImageUrl) => previewImageUrl ? {
|
|
5797
|
+
dockPreviewImageUrl: previewImageUrl,
|
|
5798
|
+
genieImageUrl: previewImageUrl
|
|
5799
|
+
} : null
|
|
5800
|
+
).catch(() => null) : Promise.resolve(null);
|
|
5801
|
+
const previewImageUrlPromise = previewImagesPromise.then(
|
|
5802
|
+
(images) => images?.genieImageUrl ?? null
|
|
5318
5803
|
);
|
|
5319
|
-
|
|
5320
|
-
|
|
5804
|
+
let preparedTexture = null;
|
|
5805
|
+
let previewImageTexture = null;
|
|
5806
|
+
const nativeFirstResult = shouldCapturePreview && !reusableTexture ? await resolveNativeFirstGenieTexture({
|
|
5807
|
+
nativeImageUrlPromise: previewImageUrlPromise,
|
|
5808
|
+
renderDomFallback: () => {
|
|
5809
|
+
preparedTexture = prepareGenieTextureCapture(
|
|
5810
|
+
resolveWorkbenchCaptureElement(nodeElement)
|
|
5811
|
+
);
|
|
5812
|
+
return preparedTexture ? renderPreparedElementTexture(preparedTexture) : null;
|
|
5813
|
+
},
|
|
5814
|
+
renderNativeImage: async (previewImageUrl) => {
|
|
5815
|
+
previewImageTexture = await renderPreviewImageTexture({
|
|
5816
|
+
previewImageUrl,
|
|
5817
|
+
rect: windowRect
|
|
5818
|
+
}).catch(() => null);
|
|
5819
|
+
return previewImageTexture;
|
|
5820
|
+
},
|
|
5821
|
+
timeoutMs: previewCaptureRaceTimeoutMs
|
|
5822
|
+
}) : null;
|
|
5823
|
+
const previewImages = nativeFirstResult?.nativeStatus === "resolved" ? await previewImagesPromise : null;
|
|
5824
|
+
const dockPreviewImageUrl = previewImages?.dockPreviewImageUrl ?? null;
|
|
5825
|
+
if (reusableTexture || nativeFirstResult?.nativeStatus === "pending") {
|
|
5321
5826
|
logWorkbenchGenieDiagnostic(
|
|
5322
5827
|
debugDiagnostics,
|
|
5323
5828
|
"workbench.genie.preview_capture.deferred",
|
|
5324
5829
|
{
|
|
5325
5830
|
...describeGenieNode(target),
|
|
5326
5831
|
mode: "genie",
|
|
5832
|
+
reusedCachedTexture: Boolean(reusableTexture),
|
|
5327
5833
|
timeoutMs: previewCaptureRaceTimeoutMs
|
|
5328
5834
|
},
|
|
5329
5835
|
"debug"
|
|
5330
5836
|
);
|
|
5331
|
-
void
|
|
5332
|
-
|
|
5837
|
+
void previewImagesPromise.then((latePreviewImages) => {
|
|
5838
|
+
const latePreviewImageUrl = latePreviewImages?.genieImageUrl;
|
|
5839
|
+
const lateDockPreviewImageUrl = latePreviewImages?.dockPreviewImageUrl;
|
|
5840
|
+
if (generation !== animationGenerationRef.current) {
|
|
5333
5841
|
return;
|
|
5334
5842
|
}
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5843
|
+
if (lateDockPreviewImageUrl) {
|
|
5844
|
+
writeCachedWorkbenchNodePreviewImage(
|
|
5845
|
+
nodeID,
|
|
5846
|
+
lateDockPreviewImageUrl
|
|
5847
|
+
);
|
|
5848
|
+
persistWorkbenchNodePreviewImage(
|
|
5849
|
+
target,
|
|
5850
|
+
lateDockPreviewImageUrl,
|
|
5851
|
+
{
|
|
5852
|
+
dockPreviewCache,
|
|
5853
|
+
resolveDockPreviewCacheKey: resolveDockPreviewCacheKey2
|
|
5854
|
+
}
|
|
5855
|
+
);
|
|
5856
|
+
}
|
|
5857
|
+
if (!latePreviewImageUrl || typeof window.requestIdleCallback !== "function") {
|
|
5858
|
+
return;
|
|
5859
|
+
}
|
|
5860
|
+
scheduleWorkbenchGeniePostAnimationIdleTask({
|
|
5861
|
+
isAnimationActive: () => rafRef.current !== null,
|
|
5862
|
+
isCancelled: () => !isMountedRef.current || generation !== animationGenerationRef.current,
|
|
5863
|
+
runTask: () => {
|
|
5864
|
+
void renderPreviewImageTexture({
|
|
5865
|
+
previewImageUrl: latePreviewImageUrl,
|
|
5866
|
+
rect: windowRect
|
|
5867
|
+
}).catch(() => null).then((refreshedTexture) => {
|
|
5868
|
+
if (refreshedTexture && generation === animationGenerationRef.current) {
|
|
5869
|
+
writeMinimizedGenieTexture(nodeID, refreshedTexture);
|
|
5870
|
+
}
|
|
5871
|
+
});
|
|
5872
|
+
},
|
|
5873
|
+
scheduler: {
|
|
5874
|
+
cancelIdleCallback: (idleID) => {
|
|
5875
|
+
window.cancelIdleCallback(idleID);
|
|
5876
|
+
},
|
|
5877
|
+
requestIdleCallback: (callback) => window.requestIdleCallback(callback)
|
|
5878
|
+
}
|
|
5339
5879
|
});
|
|
5340
5880
|
});
|
|
5341
5881
|
}
|
|
5342
|
-
const
|
|
5343
|
-
previewImageUrl,
|
|
5344
|
-
rect: windowRect
|
|
5345
|
-
}).catch(() => null) : null;
|
|
5346
|
-
const texture = componentPreviewTexture ?? previewImageTexture ?? (preparedTexture ? await renderPreparedElementTexture(preparedTexture).catch(
|
|
5347
|
-
() => null
|
|
5348
|
-
) : null);
|
|
5882
|
+
const texture = reusableTexture ?? componentPreviewTexture ?? nativeFirstResult?.texture ?? null;
|
|
5349
5883
|
if (generation !== animationGenerationRef.current) {
|
|
5350
5884
|
return;
|
|
5351
5885
|
}
|
|
@@ -5364,9 +5898,9 @@ function useWorkbenchGenieAnimation({
|
|
|
5364
5898
|
},
|
|
5365
5899
|
"warn"
|
|
5366
5900
|
);
|
|
5367
|
-
if (
|
|
5368
|
-
writeCachedWorkbenchNodePreviewImage(nodeID,
|
|
5369
|
-
persistWorkbenchNodePreviewImage(target,
|
|
5901
|
+
if (dockPreviewImageUrl) {
|
|
5902
|
+
writeCachedWorkbenchNodePreviewImage(nodeID, dockPreviewImageUrl);
|
|
5903
|
+
persistWorkbenchNodePreviewImage(target, dockPreviewImageUrl, {
|
|
5370
5904
|
dockPreviewCache,
|
|
5371
5905
|
resolveDockPreviewCacheKey: resolveDockPreviewCacheKey2
|
|
5372
5906
|
});
|
|
@@ -5374,9 +5908,9 @@ function useWorkbenchGenieAnimation({
|
|
|
5374
5908
|
runMinimize();
|
|
5375
5909
|
return;
|
|
5376
5910
|
}
|
|
5377
|
-
if (
|
|
5378
|
-
writeCachedWorkbenchNodePreviewImage(nodeID,
|
|
5379
|
-
persistWorkbenchNodePreviewImage(target,
|
|
5911
|
+
if (dockPreviewImageUrl) {
|
|
5912
|
+
writeCachedWorkbenchNodePreviewImage(nodeID, dockPreviewImageUrl);
|
|
5913
|
+
persistWorkbenchNodePreviewImage(target, dockPreviewImageUrl, {
|
|
5380
5914
|
dockPreviewCache,
|
|
5381
5915
|
resolveDockPreviewCacheKey: resolveDockPreviewCacheKey2
|
|
5382
5916
|
});
|
|
@@ -5391,7 +5925,7 @@ function useWorkbenchGenieAnimation({
|
|
|
5391
5925
|
});
|
|
5392
5926
|
}
|
|
5393
5927
|
writeMinimizedGenieTexture(nodeID, texture);
|
|
5394
|
-
|
|
5928
|
+
pruneRemovedNodeGenieTextures();
|
|
5395
5929
|
let minimizeCommitted = false;
|
|
5396
5930
|
const commitMinimize = () => {
|
|
5397
5931
|
if (minimizeCommitted) {
|
|
@@ -5453,13 +5987,19 @@ function useWorkbenchGenieAnimation({
|
|
|
5453
5987
|
cleanupPendingGenieMinimize();
|
|
5454
5988
|
},
|
|
5455
5989
|
onComplete: () => {
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
|
|
5462
|
-
|
|
5990
|
+
window.setTimeout(() => {
|
|
5991
|
+
if (!isMountedRef.current) {
|
|
5992
|
+
commitMinimize();
|
|
5993
|
+
return;
|
|
5994
|
+
}
|
|
5995
|
+
scheduleReleaseMinimizedDockEnterAnimation(nodeID);
|
|
5996
|
+
flushSync(() => {
|
|
5997
|
+
clearPendingMinimizedNode(nodeID);
|
|
5998
|
+
showNodeForGenie(nodeID);
|
|
5999
|
+
commitMinimize();
|
|
6000
|
+
});
|
|
6001
|
+
clearCanvas();
|
|
6002
|
+
}, 0);
|
|
5463
6003
|
},
|
|
5464
6004
|
skipStop: true,
|
|
5465
6005
|
texture
|
|
@@ -5474,12 +6014,14 @@ function useWorkbenchGenieAnimation({
|
|
|
5474
6014
|
clearMinimizedGenieTexture,
|
|
5475
6015
|
controller,
|
|
5476
6016
|
captureNodePreviewImage,
|
|
6017
|
+
captureNodePreviewImages,
|
|
5477
6018
|
clearPendingMinimizedNode,
|
|
5478
6019
|
debugDiagnostics,
|
|
5479
6020
|
dockPreviewCache,
|
|
5480
6021
|
hideNodeForGenie,
|
|
5481
6022
|
minimizeAnimation,
|
|
5482
|
-
|
|
6023
|
+
pruneRemovedNodeGenieTextures,
|
|
6024
|
+
readMinimizedGenieTexture,
|
|
5483
6025
|
registerMinimizedDockEnterAnimation,
|
|
5484
6026
|
releaseMinimizedDockEnterAnimation,
|
|
5485
6027
|
requestRenderedGeniePreviewTexture,
|
|
@@ -5497,17 +6039,25 @@ function useWorkbenchGenieAnimation({
|
|
|
5497
6039
|
writeMinimizedGenieTexture
|
|
5498
6040
|
]
|
|
5499
6041
|
);
|
|
5500
|
-
useEffect4(
|
|
5501
|
-
()
|
|
6042
|
+
useEffect4(() => {
|
|
6043
|
+
pruneRemovedNodeGenieTextures();
|
|
6044
|
+
return controller.subscribe(() => {
|
|
6045
|
+
pruneRemovedNodeGenieTextures();
|
|
6046
|
+
});
|
|
6047
|
+
}, [controller, pruneRemovedNodeGenieTextures]);
|
|
6048
|
+
useEffect4(() => {
|
|
6049
|
+
isMountedRef.current = true;
|
|
6050
|
+
return () => {
|
|
6051
|
+
isMountedRef.current = false;
|
|
5502
6052
|
for (const timer of minimizedDockEnterAnimationTimersRef.current.values()) {
|
|
5503
6053
|
clearTimeout(timer);
|
|
5504
6054
|
}
|
|
5505
6055
|
minimizedDockEnterAnimationTimersRef.current.clear();
|
|
5506
6056
|
minimizedDockEnterAnimationNodeIdsRef.current.clear();
|
|
5507
6057
|
minimizedGenieTextureByNodeIDRef.current.clear();
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
);
|
|
6058
|
+
nodeVisibility.dispose();
|
|
6059
|
+
};
|
|
6060
|
+
}, [nodeVisibility]);
|
|
5511
6061
|
const minimizeNodeToAnchorRef = useRef5(minimizeNodeToAnchor);
|
|
5512
6062
|
useLayoutEffect5(() => {
|
|
5513
6063
|
minimizeNodeToAnchorRef.current = minimizeNodeToAnchor;
|
|
@@ -5551,10 +6101,6 @@ function useWorkbenchGenieAnimation({
|
|
|
5551
6101
|
),
|
|
5552
6102
|
[isCanvasActive, pendingRenderedPreviewCapture]
|
|
5553
6103
|
);
|
|
5554
|
-
const isNodeGenieHidden = useCallback7(
|
|
5555
|
-
(nodeID) => genieHiddenNodeIDs.has(nodeID),
|
|
5556
|
-
[genieHiddenNodeIDs]
|
|
5557
|
-
);
|
|
5558
6104
|
const isPendingMinimizedDockNode = useCallback7(
|
|
5559
6105
|
(nodeID) => pendingMinimizedNode?.id === nodeID,
|
|
5560
6106
|
[pendingMinimizedNode]
|
|
@@ -5562,19 +6108,19 @@ function useWorkbenchGenieAnimation({
|
|
|
5562
6108
|
return useMemo6(
|
|
5563
6109
|
() => ({
|
|
5564
6110
|
genieLayer,
|
|
5565
|
-
isNodeGenieHidden,
|
|
5566
6111
|
isPendingMinimizedDockNode,
|
|
5567
6112
|
launchNodeFromAnchor,
|
|
5568
6113
|
minimizeNodeToAnchor: stableMinimizeNodeToAnchor,
|
|
6114
|
+
nodeVisibility,
|
|
5569
6115
|
pendingMinimizedNode,
|
|
5570
6116
|
registerDockAnchor,
|
|
5571
6117
|
shouldAnimateMinimizedDockEnter
|
|
5572
6118
|
}),
|
|
5573
6119
|
[
|
|
5574
6120
|
genieLayer,
|
|
5575
|
-
isNodeGenieHidden,
|
|
5576
6121
|
isPendingMinimizedDockNode,
|
|
5577
6122
|
launchNodeFromAnchor,
|
|
6123
|
+
nodeVisibility,
|
|
5578
6124
|
pendingMinimizedNode,
|
|
5579
6125
|
registerDockAnchor,
|
|
5580
6126
|
shouldAnimateMinimizedDockEnter,
|
|
@@ -5587,6 +6133,7 @@ function useWorkbenchGenieAnimation({
|
|
|
5587
6133
|
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
5588
6134
|
function WorkbenchSurface({
|
|
5589
6135
|
captureNodePreviewImage,
|
|
6136
|
+
captureNodePreviewImages,
|
|
5590
6137
|
className,
|
|
5591
6138
|
controller,
|
|
5592
6139
|
debugDiagnostics,
|
|
@@ -5624,6 +6171,7 @@ function WorkbenchSurface({
|
|
|
5624
6171
|
WorkbenchSurfaceInner,
|
|
5625
6172
|
{
|
|
5626
6173
|
captureNodePreviewImage,
|
|
6174
|
+
captureNodePreviewImages,
|
|
5627
6175
|
className,
|
|
5628
6176
|
debugDiagnostics,
|
|
5629
6177
|
dockPreviewCache,
|
|
@@ -5660,6 +6208,7 @@ function WorkbenchSurface({
|
|
|
5660
6208
|
}
|
|
5661
6209
|
function WorkbenchSurfaceInner({
|
|
5662
6210
|
captureNodePreviewImage,
|
|
6211
|
+
captureNodePreviewImages,
|
|
5663
6212
|
className,
|
|
5664
6213
|
debugDiagnostics,
|
|
5665
6214
|
dockPreviewCache,
|
|
@@ -5702,6 +6251,7 @@ function WorkbenchSurfaceInner({
|
|
|
5702
6251
|
const ref = useWorkbenchSurfaceSize(onSizeChange);
|
|
5703
6252
|
const genie = useWorkbenchGenieAnimation({
|
|
5704
6253
|
captureNodePreviewImage,
|
|
6254
|
+
captureNodePreviewImages,
|
|
5705
6255
|
controller,
|
|
5706
6256
|
debugDiagnostics,
|
|
5707
6257
|
dockPreviewCache,
|
|
@@ -6973,7 +7523,7 @@ function nullableRectsEqual(left, right) {
|
|
|
6973
7523
|
}
|
|
6974
7524
|
|
|
6975
7525
|
// src/host/externalState.ts
|
|
6976
|
-
import { useCallback as useCallback9, useMemo as useMemo7, useSyncExternalStore } from "react";
|
|
7526
|
+
import { useCallback as useCallback9, useMemo as useMemo7, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
6977
7527
|
var noopSubscribe = () => () => {
|
|
6978
7528
|
};
|
|
6979
7529
|
function createWorkbenchHostExternalStateLookupInput(input) {
|
|
@@ -7018,12 +7568,12 @@ function useWorkbenchHostExternalState(input) {
|
|
|
7018
7568
|
[input.externalStateSource, workspaceInput]
|
|
7019
7569
|
);
|
|
7020
7570
|
return {
|
|
7021
|
-
externalNodeState:
|
|
7571
|
+
externalNodeState: useSyncExternalStore2(
|
|
7022
7572
|
subscribeNodeState,
|
|
7023
7573
|
getNodeState,
|
|
7024
7574
|
getNodeState
|
|
7025
7575
|
),
|
|
7026
|
-
externalWorkspaceState:
|
|
7576
|
+
externalWorkspaceState: useSyncExternalStore2(
|
|
7027
7577
|
subscribeWorkspaceState,
|
|
7028
7578
|
getWorkspaceState,
|
|
7029
7579
|
getWorkspaceState
|
|
@@ -13715,6 +14265,7 @@ function createWorkbenchHostNodeBodyContext({
|
|
|
13715
14265
|
externalState,
|
|
13716
14266
|
externalStateSource,
|
|
13717
14267
|
host,
|
|
14268
|
+
isVisible,
|
|
13718
14269
|
workspaceId
|
|
13719
14270
|
}) {
|
|
13720
14271
|
const resolvedExternalState = externalState ?? readWorkbenchHostExternalState({
|
|
@@ -13736,6 +14287,7 @@ function createWorkbenchHostNodeBodyContext({
|
|
|
13736
14287
|
isDragging: context.isDragging,
|
|
13737
14288
|
isFocused: selectFocusedWorkbenchNode(host.getSnapshot())?.id === context.node.id,
|
|
13738
14289
|
isResizing: context.isResizing,
|
|
14290
|
+
isVisible,
|
|
13739
14291
|
presentationMode: context.layout.presentation?.mode ?? null,
|
|
13740
14292
|
node: context.node,
|
|
13741
14293
|
setNodeRuntimeState(state) {
|
|
@@ -13873,7 +14425,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
|
|
|
13873
14425
|
input.renderTopChrome,
|
|
13874
14426
|
input.workspaceId
|
|
13875
14427
|
]);
|
|
13876
|
-
const
|
|
14428
|
+
const captureNodeDefinitionPreviewImage = useCallback13(
|
|
13877
14429
|
async (node) => {
|
|
13878
14430
|
const definition = input.nodeDefinitionByType.get(node.data.typeId);
|
|
13879
14431
|
const minimizedDock = definition?.window?.minimizedDock;
|
|
@@ -13884,7 +14436,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
|
|
|
13884
14436
|
node,
|
|
13885
14437
|
workspaceId: input.workspaceId
|
|
13886
14438
|
});
|
|
13887
|
-
|
|
14439
|
+
return Promise.resolve(
|
|
13888
14440
|
capturePreview?.({
|
|
13889
14441
|
externalNodeState: externalState.externalNodeState,
|
|
13890
14442
|
externalWorkspaceState: externalState.externalWorkspaceState,
|
|
@@ -13893,19 +14445,49 @@ function useWorkbenchHostSurfaceRenderers(input) {
|
|
|
13893
14445
|
isMinimized: node.isMinimized,
|
|
13894
14446
|
node
|
|
13895
14447
|
}) ?? null
|
|
13896
|
-
).catch(() => null) ?? await Promise.resolve(
|
|
13897
|
-
input.captureNodePreviewImage?.(node) ?? null
|
|
13898
14448
|
).catch(() => null);
|
|
13899
|
-
return nodePreview;
|
|
13900
14449
|
},
|
|
13901
14450
|
[
|
|
13902
|
-
input.captureNodePreviewImage,
|
|
13903
14451
|
input.externalStateSource,
|
|
13904
14452
|
input.hostSession,
|
|
13905
14453
|
input.nodeDefinitionByType,
|
|
13906
14454
|
input.workspaceId
|
|
13907
14455
|
]
|
|
13908
14456
|
);
|
|
14457
|
+
const captureNodePreviewImage = useCallback13(
|
|
14458
|
+
async (node) => await captureNodeDefinitionPreviewImage(node) ?? await Promise.resolve(
|
|
14459
|
+
input.captureNodePreviewImage?.(node) ?? null
|
|
14460
|
+
).catch(() => null),
|
|
14461
|
+
[captureNodeDefinitionPreviewImage, input.captureNodePreviewImage]
|
|
14462
|
+
);
|
|
14463
|
+
const captureNodePreviewImages = useCallback13(
|
|
14464
|
+
async (node) => {
|
|
14465
|
+
const [images, definitionDockPreviewImageUrl] = await Promise.all([
|
|
14466
|
+
Promise.resolve(input.captureNodePreviewImages?.(node) ?? null).catch(
|
|
14467
|
+
() => null
|
|
14468
|
+
),
|
|
14469
|
+
captureNodeDefinitionPreviewImage(node)
|
|
14470
|
+
]);
|
|
14471
|
+
if (!images) {
|
|
14472
|
+
const legacyPreviewImageUrl = definitionDockPreviewImageUrl ?? await Promise.resolve(
|
|
14473
|
+
input.captureNodePreviewImage?.(node) ?? null
|
|
14474
|
+
).catch(() => null);
|
|
14475
|
+
return legacyPreviewImageUrl ? {
|
|
14476
|
+
dockPreviewImageUrl: legacyPreviewImageUrl,
|
|
14477
|
+
genieImageUrl: legacyPreviewImageUrl
|
|
14478
|
+
} : null;
|
|
14479
|
+
}
|
|
14480
|
+
return {
|
|
14481
|
+
...images,
|
|
14482
|
+
dockPreviewImageUrl: definitionDockPreviewImageUrl ?? images.dockPreviewImageUrl
|
|
14483
|
+
};
|
|
14484
|
+
},
|
|
14485
|
+
[
|
|
14486
|
+
captureNodeDefinitionPreviewImage,
|
|
14487
|
+
input.captureNodePreviewImage,
|
|
14488
|
+
input.captureNodePreviewImages
|
|
14489
|
+
]
|
|
14490
|
+
);
|
|
13909
14491
|
const renderDock = useCallback13(
|
|
13910
14492
|
(context) => /* @__PURE__ */ jsx14(
|
|
13911
14493
|
WorkbenchHostSurfaceRenderErrorBoundary,
|
|
@@ -14131,6 +14713,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
|
|
|
14131
14713
|
);
|
|
14132
14714
|
return {
|
|
14133
14715
|
captureNodePreviewImage,
|
|
14716
|
+
captureNodePreviewImages,
|
|
14134
14717
|
renderBottomChrome,
|
|
14135
14718
|
renderDock,
|
|
14136
14719
|
renderNode,
|
|
@@ -14150,6 +14733,7 @@ function useWorkbenchHostSurfaceRenderers(input) {
|
|
|
14150
14733
|
};
|
|
14151
14734
|
}
|
|
14152
14735
|
function WorkbenchHostNodeRenderer(input) {
|
|
14736
|
+
const isVisible = useWorkbenchWindowPresentationVisibility();
|
|
14153
14737
|
const externalState = useWorkbenchHostExternalState({
|
|
14154
14738
|
externalStateSource: input.externalStateSource,
|
|
14155
14739
|
node: input.context.node,
|
|
@@ -14161,6 +14745,7 @@ function WorkbenchHostNodeRenderer(input) {
|
|
|
14161
14745
|
externalState,
|
|
14162
14746
|
externalStateSource: input.externalStateSource,
|
|
14163
14747
|
host: input.host,
|
|
14748
|
+
isVisible,
|
|
14164
14749
|
workspaceId: input.workspaceId
|
|
14165
14750
|
});
|
|
14166
14751
|
const resetKey = useMemo10(
|
|
@@ -14428,6 +15013,7 @@ var noop3 = () => {
|
|
|
14428
15013
|
};
|
|
14429
15014
|
function WorkbenchHost({
|
|
14430
15015
|
captureNodePreviewImage,
|
|
15016
|
+
captureNodePreviewImages,
|
|
14431
15017
|
className,
|
|
14432
15018
|
contributions,
|
|
14433
15019
|
debugDiagnostics,
|
|
@@ -14512,6 +15098,7 @@ function WorkbenchHost({
|
|
|
14512
15098
|
});
|
|
14513
15099
|
const surfaceRenderers = useWorkbenchHostSurfaceRenderers({
|
|
14514
15100
|
captureNodePreviewImage,
|
|
15101
|
+
captureNodePreviewImages,
|
|
14515
15102
|
chromeContext,
|
|
14516
15103
|
debugDiagnostics,
|
|
14517
15104
|
dockPreviewCache,
|
|
@@ -14543,6 +15130,7 @@ function WorkbenchHost({
|
|
|
14543
15130
|
{
|
|
14544
15131
|
className,
|
|
14545
15132
|
captureNodePreviewImage: surfaceRenderers.captureNodePreviewImage,
|
|
15133
|
+
captureNodePreviewImages: surfaceRenderers.captureNodePreviewImages,
|
|
14546
15134
|
controller: hostSession.controller,
|
|
14547
15135
|
debugDiagnostics,
|
|
14548
15136
|
dockPreviewCache,
|