@lvce-editor/extension-host-worker 8.33.0 → 8.35.0
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/extension-api/index.js +175 -9
- package/dist/extension-api/parts/ExtensionApiCommandMap/ExtensionApiCommandMap.js +4 -0
- package/dist/extension-api/parts/ViewRegistry/ViewRegistry.js +175 -9
- package/extension-api/dist/index.d.ts +2 -2
- package/extension-api/dist/index.js +1 -1
- package/extension-api/dist/parts/CommandMap/CommandMap.d.ts +2 -0
- package/extension-api/dist/parts/ExtensionApiCommandMap/ExtensionApiCommandMap.d.ts +2 -0
- package/extension-api/dist/parts/ExtensionApiCommandMap/ExtensionApiCommandMap.js +3 -1
- package/extension-api/dist/parts/ExtensionApiWorkerCommandMap/ExtensionApiWorkerCommandMap.d.ts +2 -0
- package/extension-api/dist/parts/View/View.d.ts +27 -0
- package/extension-api/dist/parts/ViewRegistry/ViewRegistry.d.ts +3 -1
- package/extension-api/dist/parts/ViewRegistry/ViewRegistry.js +174 -9
- package/extension-api/package.json +1 -1
- package/extension-api/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -2393,6 +2393,50 @@ var diffTree = (oldNodes, newNodes) => {
|
|
|
2393
2393
|
var views = /* @__PURE__ */ Object.create(null);
|
|
2394
2394
|
var instances = /* @__PURE__ */ Object.create(null);
|
|
2395
2395
|
var renderedDoms = /* @__PURE__ */ Object.create(null);
|
|
2396
|
+
var contexts = /* @__PURE__ */ Object.create(null);
|
|
2397
|
+
var contextViewIds = /* @__PURE__ */ Object.create(null);
|
|
2398
|
+
var assertBoolean = (value, message) => {
|
|
2399
|
+
if (value !== void 0 && typeof value !== "boolean") {
|
|
2400
|
+
throw new ExtensionApiError(message);
|
|
2401
|
+
}
|
|
2402
|
+
};
|
|
2403
|
+
var assertNumber = (value, message) => {
|
|
2404
|
+
if (typeof value !== "number") {
|
|
2405
|
+
throw new ExtensionApiError(message);
|
|
2406
|
+
}
|
|
2407
|
+
};
|
|
2408
|
+
var assertString = (value, message) => {
|
|
2409
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
2410
|
+
throw new ExtensionApiError(message);
|
|
2411
|
+
}
|
|
2412
|
+
};
|
|
2413
|
+
var assertEventListener = (viewId, listener, index) => {
|
|
2414
|
+
if (!listener || typeof listener !== "object") {
|
|
2415
|
+
throw new ExtensionApiError(`view ${viewId} event listener ${index} must be an object`);
|
|
2416
|
+
}
|
|
2417
|
+
const eventListener = listener;
|
|
2418
|
+
if (typeof eventListener.name !== "string" && typeof eventListener.name !== "number") {
|
|
2419
|
+
throw new ExtensionApiError(`view ${viewId} event listener ${index} is missing name`);
|
|
2420
|
+
}
|
|
2421
|
+
if (!Array.isArray(eventListener.params) || eventListener.params.some((param) => typeof param !== "string")) {
|
|
2422
|
+
throw new ExtensionApiError(`view ${viewId} event listener ${index} is missing params`);
|
|
2423
|
+
}
|
|
2424
|
+
assertBoolean(eventListener.capture, `view ${viewId} event listener ${index} has invalid capture`);
|
|
2425
|
+
assertBoolean(eventListener.passive, `view ${viewId} event listener ${index} has invalid passive`);
|
|
2426
|
+
assertBoolean(eventListener.preventDefault, `view ${viewId} event listener ${index} has invalid preventDefault`);
|
|
2427
|
+
assertBoolean(eventListener.stopPropagation, `view ${viewId} event listener ${index} has invalid stopPropagation`);
|
|
2428
|
+
};
|
|
2429
|
+
var assertEventListeners = (view) => {
|
|
2430
|
+
if (view.eventListeners === void 0) {
|
|
2431
|
+
return;
|
|
2432
|
+
}
|
|
2433
|
+
if (!Array.isArray(view.eventListeners)) {
|
|
2434
|
+
throw new ExtensionApiError(`view ${view.id} eventListeners must be an array`);
|
|
2435
|
+
}
|
|
2436
|
+
for (const [index, listener] of view.eventListeners.entries()) {
|
|
2437
|
+
assertEventListener(view.id, listener, index);
|
|
2438
|
+
}
|
|
2439
|
+
};
|
|
2396
2440
|
var assertView = (view) => {
|
|
2397
2441
|
if (!view) {
|
|
2398
2442
|
throw new ExtensionApiError("view is not defined");
|
|
@@ -2406,12 +2450,17 @@ var assertView = (view) => {
|
|
|
2406
2450
|
if (view.id in views) {
|
|
2407
2451
|
throw new ExtensionApiError(`view ${view.id} is already registered`);
|
|
2408
2452
|
}
|
|
2453
|
+
assertEventListeners(view);
|
|
2409
2454
|
};
|
|
2410
2455
|
var toRegisteredView = (view) => {
|
|
2456
|
+
const displayName = view.displayName || view.name || view.title;
|
|
2411
2457
|
const registeredView = {
|
|
2458
|
+
displayName,
|
|
2459
|
+
...view.eventListeners && { eventListeners: view.eventListeners },
|
|
2412
2460
|
icon: view.icon,
|
|
2413
2461
|
id: view.id,
|
|
2414
|
-
|
|
2462
|
+
name: view.name,
|
|
2463
|
+
title: displayName
|
|
2415
2464
|
};
|
|
2416
2465
|
if (view.kind) {
|
|
2417
2466
|
return {
|
|
@@ -2459,6 +2508,92 @@ var renderDom = async (instance) => {
|
|
|
2459
2508
|
}
|
|
2460
2509
|
return dom;
|
|
2461
2510
|
};
|
|
2511
|
+
var normalizeMenuEntry = (entry, index) => {
|
|
2512
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
|
2513
|
+
throw new ExtensionApiError(`menu entry ${index} must be an object`);
|
|
2514
|
+
}
|
|
2515
|
+
const menuEntry = entry;
|
|
2516
|
+
assertString(menuEntry.id, `menu entry ${index} is missing id`);
|
|
2517
|
+
assertString(menuEntry.label, `menu entry ${index} is missing label`);
|
|
2518
|
+
assertString(menuEntry.command, `menu entry ${index} is missing command`);
|
|
2519
|
+
if (menuEntry.flags !== void 0 && typeof menuEntry.flags !== "number") {
|
|
2520
|
+
throw new ExtensionApiError(`menu entry ${index} has invalid flags`);
|
|
2521
|
+
}
|
|
2522
|
+
if (menuEntry.args !== void 0 && !Array.isArray(menuEntry.args)) {
|
|
2523
|
+
throw new ExtensionApiError(`menu entry ${index} has invalid args`);
|
|
2524
|
+
}
|
|
2525
|
+
return {
|
|
2526
|
+
command: menuEntry.command,
|
|
2527
|
+
flags: menuEntry.flags ?? 0,
|
|
2528
|
+
id: menuEntry.id,
|
|
2529
|
+
label: menuEntry.label,
|
|
2530
|
+
...menuEntry.args && { args: menuEntry.args }
|
|
2531
|
+
};
|
|
2532
|
+
};
|
|
2533
|
+
var normalizeMenuEntries = (entries) => {
|
|
2534
|
+
if (!Array.isArray(entries)) {
|
|
2535
|
+
throw new ExtensionApiError("view menu entries must be an array");
|
|
2536
|
+
}
|
|
2537
|
+
return entries.map(normalizeMenuEntry);
|
|
2538
|
+
};
|
|
2539
|
+
var renderPatches = async (uid, instance) => {
|
|
2540
|
+
const oldDom = renderedDoms[uid] || [];
|
|
2541
|
+
const newDom = await renderDom(instance);
|
|
2542
|
+
renderedDoms[uid] = newDom;
|
|
2543
|
+
const patches = diffTree(oldDom, newDom);
|
|
2544
|
+
return {
|
|
2545
|
+
patches,
|
|
2546
|
+
type: "setPatches"
|
|
2547
|
+
};
|
|
2548
|
+
};
|
|
2549
|
+
var normalizeContext = (context) => {
|
|
2550
|
+
if (!context || typeof context !== "object" || Array.isArray(context)) {
|
|
2551
|
+
return {};
|
|
2552
|
+
}
|
|
2553
|
+
const normalized = {};
|
|
2554
|
+
for (const [key, value] of Object.entries(context)) {
|
|
2555
|
+
if (typeof value === "boolean") {
|
|
2556
|
+
normalized[key] = value;
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
return normalized;
|
|
2560
|
+
};
|
|
2561
|
+
var isSameContext = (oldContext, newContext) => {
|
|
2562
|
+
const oldKeys = Object.keys(oldContext);
|
|
2563
|
+
const newKeys = Object.keys(newContext);
|
|
2564
|
+
if (oldKeys.length !== newKeys.length) {
|
|
2565
|
+
return false;
|
|
2566
|
+
}
|
|
2567
|
+
for (const key of oldKeys) {
|
|
2568
|
+
if (oldContext[key] !== newContext[key]) {
|
|
2569
|
+
return false;
|
|
2570
|
+
}
|
|
2571
|
+
}
|
|
2572
|
+
return true;
|
|
2573
|
+
};
|
|
2574
|
+
var maybeNotifyContextChanged = async (uid, viewId, instance) => {
|
|
2575
|
+
if (typeof instance.getContext !== "function") {
|
|
2576
|
+
return;
|
|
2577
|
+
}
|
|
2578
|
+
const oldContext = contexts[uid] || {};
|
|
2579
|
+
const newContext = normalizeContext(instance.getContext());
|
|
2580
|
+
if (isSameContext(oldContext, newContext)) {
|
|
2581
|
+
return;
|
|
2582
|
+
}
|
|
2583
|
+
if (Object.keys(newContext).length === 0) {
|
|
2584
|
+
delete contexts[uid];
|
|
2585
|
+
} else {
|
|
2586
|
+
contexts[uid] = newContext;
|
|
2587
|
+
}
|
|
2588
|
+
await ExtensionManagementWorker_exports.invoke("Extensions.handleViewContextChange", uid, viewId, newContext);
|
|
2589
|
+
};
|
|
2590
|
+
var maybeClearContext = async (uid, viewId) => {
|
|
2591
|
+
if (!contexts[uid]) {
|
|
2592
|
+
return;
|
|
2593
|
+
}
|
|
2594
|
+
delete contexts[uid];
|
|
2595
|
+
await ExtensionManagementWorker_exports.invoke("Extensions.handleViewContextChange", uid, viewId, {});
|
|
2596
|
+
};
|
|
2462
2597
|
var createViewInstance = async (viewId, uid, context) => {
|
|
2463
2598
|
const view = views[viewId];
|
|
2464
2599
|
if (!view) {
|
|
@@ -2469,13 +2604,24 @@ var createViewInstance = async (viewId, uid, context) => {
|
|
|
2469
2604
|
}
|
|
2470
2605
|
const instance = await view.create({
|
|
2471
2606
|
...context,
|
|
2607
|
+
requestRerender() {
|
|
2608
|
+
return ExtensionManagementWorker_exports.invoke("Extensions.requestViewRerender", uid);
|
|
2609
|
+
},
|
|
2610
|
+
showContextMenu(menuId, x, y) {
|
|
2611
|
+
assertString(menuId, "menuId must be a string");
|
|
2612
|
+
assertNumber(x, "x must be a number");
|
|
2613
|
+
assertNumber(y, "y must be a number");
|
|
2614
|
+
return ExtensionManagementWorker_exports.invoke("Extensions.showViewContextMenu", uid, viewId, menuId, x, y);
|
|
2615
|
+
},
|
|
2472
2616
|
uid,
|
|
2473
2617
|
viewId
|
|
2474
2618
|
});
|
|
2475
2619
|
assertVirtualDomViewInstance(viewId, instance);
|
|
2476
2620
|
instances[uid] = instance;
|
|
2621
|
+
contextViewIds[uid] = viewId;
|
|
2477
2622
|
const dom = await renderDom(instance);
|
|
2478
2623
|
renderedDoms[uid] = dom;
|
|
2624
|
+
await maybeNotifyContextChanged(uid, viewId, instance);
|
|
2479
2625
|
return {
|
|
2480
2626
|
dom,
|
|
2481
2627
|
type: "setDom"
|
|
@@ -2486,22 +2632,25 @@ var dispatchViewEvent = async (uid, event) => {
|
|
|
2486
2632
|
if (typeof instance.handleEvent === "function") {
|
|
2487
2633
|
await instance.handleEvent(event);
|
|
2488
2634
|
}
|
|
2489
|
-
const
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2635
|
+
const result = await renderPatches(uid, instance);
|
|
2636
|
+
await maybeNotifyContextChanged(uid, contextViewIds[uid], instance);
|
|
2637
|
+
return result;
|
|
2638
|
+
};
|
|
2639
|
+
var renderViewInstance = async (uid) => {
|
|
2640
|
+
const instance = getVirtualDomInstance(uid);
|
|
2641
|
+
const result = await renderPatches(uid, instance);
|
|
2642
|
+
await maybeNotifyContextChanged(uid, contextViewIds[uid], instance);
|
|
2643
|
+
return result;
|
|
2497
2644
|
};
|
|
2498
2645
|
var disposeViewInstance = async (uid) => {
|
|
2499
2646
|
const instance = instances[uid];
|
|
2500
2647
|
if (instance && typeof instance.dispose === "function") {
|
|
2501
2648
|
await instance.dispose();
|
|
2502
2649
|
}
|
|
2650
|
+
await maybeClearContext(uid, contextViewIds[uid]);
|
|
2503
2651
|
delete instances[uid];
|
|
2504
2652
|
delete renderedDoms[uid];
|
|
2653
|
+
delete contextViewIds[uid];
|
|
2505
2654
|
};
|
|
2506
2655
|
var saveViewInstanceState = async (uid) => {
|
|
2507
2656
|
const instance = getVirtualDomInstance(uid);
|
|
@@ -2510,6 +2659,14 @@ var saveViewInstanceState = async (uid) => {
|
|
|
2510
2659
|
}
|
|
2511
2660
|
return instance.saveState();
|
|
2512
2661
|
};
|
|
2662
|
+
var getViewMenuEntries = async (uid, menuId) => {
|
|
2663
|
+
assertString(menuId, "menuId must be a string");
|
|
2664
|
+
const instance = getVirtualDomInstance(uid);
|
|
2665
|
+
if (typeof instance.getMenuEntries !== "function") {
|
|
2666
|
+
return [];
|
|
2667
|
+
}
|
|
2668
|
+
return normalizeMenuEntries(await instance.getMenuEntries(menuId));
|
|
2669
|
+
};
|
|
2513
2670
|
var getViewRegistrySnapshot = () => {
|
|
2514
2671
|
return {
|
|
2515
2672
|
views: Object.values(views).map(toRegisteredView)
|
|
@@ -2525,6 +2682,12 @@ var resetViewRegistry = () => {
|
|
|
2525
2682
|
for (const uid of Object.keys(renderedDoms)) {
|
|
2526
2683
|
delete renderedDoms[Number(uid)];
|
|
2527
2684
|
}
|
|
2685
|
+
for (const uid of Object.keys(contexts)) {
|
|
2686
|
+
delete contexts[Number(uid)];
|
|
2687
|
+
}
|
|
2688
|
+
for (const uid of Object.keys(contextViewIds)) {
|
|
2689
|
+
delete contextViewIds[Number(uid)];
|
|
2690
|
+
}
|
|
2528
2691
|
};
|
|
2529
2692
|
|
|
2530
2693
|
// packages/extension-api/src/parts/ExtensionApiCommandMap/ExtensionApiCommandMap.ts
|
|
@@ -2557,7 +2720,9 @@ var commandMap = {
|
|
|
2557
2720
|
"ExtensionApi.getOutputChannelRegistrySnapshot": getOutputChannelRegistrySnapshot,
|
|
2558
2721
|
"ExtensionApi.getSourceControlProviderRegistrySnapshot": getSourceControlProviderRegistrySnapshot,
|
|
2559
2722
|
"ExtensionApi.getStatusBarItems": getStatusBarItems,
|
|
2723
|
+
"ExtensionApi.getViewMenuEntries": getViewMenuEntries,
|
|
2560
2724
|
"ExtensionApi.getViewRegistrySnapshot": getViewRegistrySnapshot,
|
|
2725
|
+
"ExtensionApi.renderViewInstance": renderViewInstance,
|
|
2561
2726
|
"ExtensionApi.saveViewInstanceState": saveViewInstanceState
|
|
2562
2727
|
};
|
|
2563
2728
|
|
|
@@ -2744,6 +2909,7 @@ export {
|
|
|
2744
2909
|
registerStatusBarItemProvider,
|
|
2745
2910
|
registerView,
|
|
2746
2911
|
remove4 as remove,
|
|
2912
|
+
renderViewInstance,
|
|
2747
2913
|
resetCompletionProviderRegistry,
|
|
2748
2914
|
resetDiagnosticProviderRegistry,
|
|
2749
2915
|
resetFormattingProviderRegistry,
|
|
@@ -23,7 +23,9 @@ import {
|
|
|
23
23
|
dispatchViewEvent,
|
|
24
24
|
disposeViewInstance,
|
|
25
25
|
executeViewProvider,
|
|
26
|
+
getViewMenuEntries,
|
|
26
27
|
getViewRegistrySnapshot,
|
|
28
|
+
renderViewInstance,
|
|
27
29
|
saveViewInstanceState
|
|
28
30
|
} from "../ViewRegistry/ViewRegistry.js";
|
|
29
31
|
const commandMap = {
|
|
@@ -55,7 +57,9 @@ const commandMap = {
|
|
|
55
57
|
"ExtensionApi.getOutputChannelRegistrySnapshot": getOutputChannelRegistrySnapshot,
|
|
56
58
|
"ExtensionApi.getSourceControlProviderRegistrySnapshot": getSourceControlProviderRegistrySnapshot,
|
|
57
59
|
"ExtensionApi.getStatusBarItems": getStatusBarItems,
|
|
60
|
+
"ExtensionApi.getViewMenuEntries": getViewMenuEntries,
|
|
58
61
|
"ExtensionApi.getViewRegistrySnapshot": getViewRegistrySnapshot,
|
|
62
|
+
"ExtensionApi.renderViewInstance": renderViewInstance,
|
|
59
63
|
"ExtensionApi.saveViewInstanceState": saveViewInstanceState
|
|
60
64
|
};
|
|
61
65
|
export {
|
|
@@ -1,8 +1,53 @@
|
|
|
1
|
+
import { ExtensionManagementWorker } from "@lvce-editor/rpc-registry";
|
|
1
2
|
import { diffTree } from "@lvce-editor/virtual-dom-worker";
|
|
2
3
|
import { ExtensionApiError } from "../ExtensionApiError/ExtensionApiError.js";
|
|
3
4
|
const views = /* @__PURE__ */ Object.create(null);
|
|
4
5
|
const instances = /* @__PURE__ */ Object.create(null);
|
|
5
6
|
const renderedDoms = /* @__PURE__ */ Object.create(null);
|
|
7
|
+
const contexts = /* @__PURE__ */ Object.create(null);
|
|
8
|
+
const contextViewIds = /* @__PURE__ */ Object.create(null);
|
|
9
|
+
const assertBoolean = (value, message) => {
|
|
10
|
+
if (value !== void 0 && typeof value !== "boolean") {
|
|
11
|
+
throw new ExtensionApiError(message);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
const assertNumber = (value, message) => {
|
|
15
|
+
if (typeof value !== "number") {
|
|
16
|
+
throw new ExtensionApiError(message);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
const assertString = (value, message) => {
|
|
20
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
21
|
+
throw new ExtensionApiError(message);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const assertEventListener = (viewId, listener, index) => {
|
|
25
|
+
if (!listener || typeof listener !== "object") {
|
|
26
|
+
throw new ExtensionApiError(`view ${viewId} event listener ${index} must be an object`);
|
|
27
|
+
}
|
|
28
|
+
const eventListener = listener;
|
|
29
|
+
if (typeof eventListener.name !== "string" && typeof eventListener.name !== "number") {
|
|
30
|
+
throw new ExtensionApiError(`view ${viewId} event listener ${index} is missing name`);
|
|
31
|
+
}
|
|
32
|
+
if (!Array.isArray(eventListener.params) || eventListener.params.some((param) => typeof param !== "string")) {
|
|
33
|
+
throw new ExtensionApiError(`view ${viewId} event listener ${index} is missing params`);
|
|
34
|
+
}
|
|
35
|
+
assertBoolean(eventListener.capture, `view ${viewId} event listener ${index} has invalid capture`);
|
|
36
|
+
assertBoolean(eventListener.passive, `view ${viewId} event listener ${index} has invalid passive`);
|
|
37
|
+
assertBoolean(eventListener.preventDefault, `view ${viewId} event listener ${index} has invalid preventDefault`);
|
|
38
|
+
assertBoolean(eventListener.stopPropagation, `view ${viewId} event listener ${index} has invalid stopPropagation`);
|
|
39
|
+
};
|
|
40
|
+
const assertEventListeners = (view) => {
|
|
41
|
+
if (view.eventListeners === void 0) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (!Array.isArray(view.eventListeners)) {
|
|
45
|
+
throw new ExtensionApiError(`view ${view.id} eventListeners must be an array`);
|
|
46
|
+
}
|
|
47
|
+
for (const [index, listener] of view.eventListeners.entries()) {
|
|
48
|
+
assertEventListener(view.id, listener, index);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
6
51
|
const assertView = (view) => {
|
|
7
52
|
if (!view) {
|
|
8
53
|
throw new ExtensionApiError("view is not defined");
|
|
@@ -16,12 +61,17 @@ const assertView = (view) => {
|
|
|
16
61
|
if (view.id in views) {
|
|
17
62
|
throw new ExtensionApiError(`view ${view.id} is already registered`);
|
|
18
63
|
}
|
|
64
|
+
assertEventListeners(view);
|
|
19
65
|
};
|
|
20
66
|
const toRegisteredView = (view) => {
|
|
67
|
+
const displayName = view.displayName || view.name || view.title;
|
|
21
68
|
const registeredView = {
|
|
69
|
+
displayName,
|
|
70
|
+
...view.eventListeners && { eventListeners: view.eventListeners },
|
|
22
71
|
icon: view.icon,
|
|
23
72
|
id: view.id,
|
|
24
|
-
|
|
73
|
+
name: view.name,
|
|
74
|
+
title: displayName
|
|
25
75
|
};
|
|
26
76
|
if (view.kind) {
|
|
27
77
|
return {
|
|
@@ -69,6 +119,92 @@ const renderDom = async (instance) => {
|
|
|
69
119
|
}
|
|
70
120
|
return dom;
|
|
71
121
|
};
|
|
122
|
+
const normalizeMenuEntry = (entry, index) => {
|
|
123
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
|
124
|
+
throw new ExtensionApiError(`menu entry ${index} must be an object`);
|
|
125
|
+
}
|
|
126
|
+
const menuEntry = entry;
|
|
127
|
+
assertString(menuEntry.id, `menu entry ${index} is missing id`);
|
|
128
|
+
assertString(menuEntry.label, `menu entry ${index} is missing label`);
|
|
129
|
+
assertString(menuEntry.command, `menu entry ${index} is missing command`);
|
|
130
|
+
if (menuEntry.flags !== void 0 && typeof menuEntry.flags !== "number") {
|
|
131
|
+
throw new ExtensionApiError(`menu entry ${index} has invalid flags`);
|
|
132
|
+
}
|
|
133
|
+
if (menuEntry.args !== void 0 && !Array.isArray(menuEntry.args)) {
|
|
134
|
+
throw new ExtensionApiError(`menu entry ${index} has invalid args`);
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
command: menuEntry.command,
|
|
138
|
+
flags: menuEntry.flags ?? 0,
|
|
139
|
+
id: menuEntry.id,
|
|
140
|
+
label: menuEntry.label,
|
|
141
|
+
...menuEntry.args && { args: menuEntry.args }
|
|
142
|
+
};
|
|
143
|
+
};
|
|
144
|
+
const normalizeMenuEntries = (entries) => {
|
|
145
|
+
if (!Array.isArray(entries)) {
|
|
146
|
+
throw new ExtensionApiError("view menu entries must be an array");
|
|
147
|
+
}
|
|
148
|
+
return entries.map(normalizeMenuEntry);
|
|
149
|
+
};
|
|
150
|
+
const renderPatches = async (uid, instance) => {
|
|
151
|
+
const oldDom = renderedDoms[uid] || [];
|
|
152
|
+
const newDom = await renderDom(instance);
|
|
153
|
+
renderedDoms[uid] = newDom;
|
|
154
|
+
const patches = diffTree(oldDom, newDom);
|
|
155
|
+
return {
|
|
156
|
+
patches,
|
|
157
|
+
type: "setPatches"
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
const normalizeContext = (context) => {
|
|
161
|
+
if (!context || typeof context !== "object" || Array.isArray(context)) {
|
|
162
|
+
return {};
|
|
163
|
+
}
|
|
164
|
+
const normalized = {};
|
|
165
|
+
for (const [key, value] of Object.entries(context)) {
|
|
166
|
+
if (typeof value === "boolean") {
|
|
167
|
+
normalized[key] = value;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return normalized;
|
|
171
|
+
};
|
|
172
|
+
const isSameContext = (oldContext, newContext) => {
|
|
173
|
+
const oldKeys = Object.keys(oldContext);
|
|
174
|
+
const newKeys = Object.keys(newContext);
|
|
175
|
+
if (oldKeys.length !== newKeys.length) {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
for (const key of oldKeys) {
|
|
179
|
+
if (oldContext[key] !== newContext[key]) {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return true;
|
|
184
|
+
};
|
|
185
|
+
const maybeNotifyContextChanged = async (uid, viewId, instance) => {
|
|
186
|
+
if (typeof instance.getContext !== "function") {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const oldContext = contexts[uid] || {};
|
|
190
|
+
const newContext = normalizeContext(instance.getContext());
|
|
191
|
+
if (isSameContext(oldContext, newContext)) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
if (Object.keys(newContext).length === 0) {
|
|
195
|
+
delete contexts[uid];
|
|
196
|
+
} else {
|
|
197
|
+
contexts[uid] = newContext;
|
|
198
|
+
}
|
|
199
|
+
await ExtensionManagementWorker.invoke("Extensions.handleViewContextChange", uid, viewId, newContext);
|
|
200
|
+
};
|
|
201
|
+
const maybeClearContext = async (uid, viewId) => {
|
|
202
|
+
if (!contexts[uid]) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
delete contexts[uid];
|
|
206
|
+
await ExtensionManagementWorker.invoke("Extensions.handleViewContextChange", uid, viewId, {});
|
|
207
|
+
};
|
|
72
208
|
const createViewInstance = async (viewId, uid, context) => {
|
|
73
209
|
const view = views[viewId];
|
|
74
210
|
if (!view) {
|
|
@@ -79,13 +215,24 @@ const createViewInstance = async (viewId, uid, context) => {
|
|
|
79
215
|
}
|
|
80
216
|
const instance = await view.create({
|
|
81
217
|
...context,
|
|
218
|
+
requestRerender() {
|
|
219
|
+
return ExtensionManagementWorker.invoke("Extensions.requestViewRerender", uid);
|
|
220
|
+
},
|
|
221
|
+
showContextMenu(menuId, x, y) {
|
|
222
|
+
assertString(menuId, "menuId must be a string");
|
|
223
|
+
assertNumber(x, "x must be a number");
|
|
224
|
+
assertNumber(y, "y must be a number");
|
|
225
|
+
return ExtensionManagementWorker.invoke("Extensions.showViewContextMenu", uid, viewId, menuId, x, y);
|
|
226
|
+
},
|
|
82
227
|
uid,
|
|
83
228
|
viewId
|
|
84
229
|
});
|
|
85
230
|
assertVirtualDomViewInstance(viewId, instance);
|
|
86
231
|
instances[uid] = instance;
|
|
232
|
+
contextViewIds[uid] = viewId;
|
|
87
233
|
const dom = await renderDom(instance);
|
|
88
234
|
renderedDoms[uid] = dom;
|
|
235
|
+
await maybeNotifyContextChanged(uid, viewId, instance);
|
|
89
236
|
return {
|
|
90
237
|
dom,
|
|
91
238
|
type: "setDom"
|
|
@@ -96,22 +243,25 @@ const dispatchViewEvent = async (uid, event) => {
|
|
|
96
243
|
if (typeof instance.handleEvent === "function") {
|
|
97
244
|
await instance.handleEvent(event);
|
|
98
245
|
}
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
246
|
+
const result = await renderPatches(uid, instance);
|
|
247
|
+
await maybeNotifyContextChanged(uid, contextViewIds[uid], instance);
|
|
248
|
+
return result;
|
|
249
|
+
};
|
|
250
|
+
const renderViewInstance = async (uid) => {
|
|
251
|
+
const instance = getVirtualDomInstance(uid);
|
|
252
|
+
const result = await renderPatches(uid, instance);
|
|
253
|
+
await maybeNotifyContextChanged(uid, contextViewIds[uid], instance);
|
|
254
|
+
return result;
|
|
107
255
|
};
|
|
108
256
|
const disposeViewInstance = async (uid) => {
|
|
109
257
|
const instance = instances[uid];
|
|
110
258
|
if (instance && typeof instance.dispose === "function") {
|
|
111
259
|
await instance.dispose();
|
|
112
260
|
}
|
|
261
|
+
await maybeClearContext(uid, contextViewIds[uid]);
|
|
113
262
|
delete instances[uid];
|
|
114
263
|
delete renderedDoms[uid];
|
|
264
|
+
delete contextViewIds[uid];
|
|
115
265
|
};
|
|
116
266
|
const saveViewInstanceState = async (uid) => {
|
|
117
267
|
const instance = getVirtualDomInstance(uid);
|
|
@@ -120,6 +270,14 @@ const saveViewInstanceState = async (uid) => {
|
|
|
120
270
|
}
|
|
121
271
|
return instance.saveState();
|
|
122
272
|
};
|
|
273
|
+
const getViewMenuEntries = async (uid, menuId) => {
|
|
274
|
+
assertString(menuId, "menuId must be a string");
|
|
275
|
+
const instance = getVirtualDomInstance(uid);
|
|
276
|
+
if (typeof instance.getMenuEntries !== "function") {
|
|
277
|
+
return [];
|
|
278
|
+
}
|
|
279
|
+
return normalizeMenuEntries(await instance.getMenuEntries(menuId));
|
|
280
|
+
};
|
|
123
281
|
const getViewRegistrySnapshot = () => {
|
|
124
282
|
return {
|
|
125
283
|
views: Object.values(views).map(toRegisteredView)
|
|
@@ -135,14 +293,22 @@ const resetViewRegistry = () => {
|
|
|
135
293
|
for (const uid of Object.keys(renderedDoms)) {
|
|
136
294
|
delete renderedDoms[Number(uid)];
|
|
137
295
|
}
|
|
296
|
+
for (const uid of Object.keys(contexts)) {
|
|
297
|
+
delete contexts[Number(uid)];
|
|
298
|
+
}
|
|
299
|
+
for (const uid of Object.keys(contextViewIds)) {
|
|
300
|
+
delete contextViewIds[Number(uid)];
|
|
301
|
+
}
|
|
138
302
|
};
|
|
139
303
|
export {
|
|
140
304
|
createViewInstance,
|
|
141
305
|
dispatchViewEvent,
|
|
142
306
|
disposeViewInstance,
|
|
143
307
|
executeViewProvider,
|
|
308
|
+
getViewMenuEntries,
|
|
144
309
|
getViewRegistrySnapshot,
|
|
145
310
|
registerView,
|
|
311
|
+
renderViewInstance,
|
|
146
312
|
resetViewRegistry,
|
|
147
313
|
saveViewInstanceState
|
|
148
314
|
};
|
|
@@ -9,10 +9,10 @@ export { executeFormattingProvider, getFormattingProviderRegistrySnapshot, regis
|
|
|
9
9
|
export { exists, mkdir, readDirWithFileTypes, readFile, remove, writeFile } from './parts/FileSystem/FileSystem.ts';
|
|
10
10
|
export { executeHoverProvider, getHoverProviderRegistrySnapshot, registerHoverProvider, resetHoverProviderRegistry } from './parts/Hover/Hover.ts';
|
|
11
11
|
export { executeSourceControlAcceptInput, executeSourceControlAdd, executeSourceControlDiscard, executeSourceControlGenerateCommitMessage, executeSourceControlGetChangedFiles, executeSourceControlGetFeatures, executeSourceControlGetFileBefore, executeSourceControlGetFileDecorations, executeSourceControlGetGroups, executeSourceControlIsActive, registerSourceControlProvider, resetSourceControlProviderRegistry, } from './parts/SourceControl/SourceControl.ts';
|
|
12
|
-
export { createViewInstance, dispatchViewEvent, disposeViewInstance, executeViewProvider, getViewRegistrySnapshot, registerView, resetViewRegistry, saveViewInstanceState, } from './parts/ViewRegistry/ViewRegistry.ts';
|
|
12
|
+
export { createViewInstance, dispatchViewEvent, disposeViewInstance, executeViewProvider, getViewRegistrySnapshot, renderViewInstance, registerView, resetViewRegistry, saveViewInstanceState, } from './parts/ViewRegistry/ViewRegistry.ts';
|
|
13
13
|
export { createOutputChannel, getOutputChannelRegistrySnapshot, resetOutputChannelRegistry } from './parts/OutputChannel/OutputChannel.ts';
|
|
14
14
|
export { getStatusBarItemProviderRegistrySnapshot, registerStatusBarItemProvider, resetStatusBarItemProviderRegistry, } from './parts/StatusBar/StatusBar.ts';
|
|
15
|
-
export type { RegisteredView, View, ViewContext, ViewEvent, ViewKind, ViewRegistrySnapshot, ViewRenderResult, VirtualDomViewInstance, } from './parts/View/View.ts';
|
|
15
|
+
export type { RegisteredView, View, ViewContext, ViewEvent, ViewKind, MenuEntry, ViewRegistrySnapshot, ViewRenderResult, VirtualDomViewInstance, } from './parts/View/View.ts';
|
|
16
16
|
export { handleExtensionManagementMessagePort } from './parts/HandleExtensionManagementMessagePort/HandleExtensionManagementMessagePort.ts';
|
|
17
17
|
export type { Command } from './parts/Command/Command.ts';
|
|
18
18
|
export type { CommandCallback } from './parts/CommandCallback/CommandCallback.ts';
|
|
@@ -9,7 +9,7 @@ export { executeFormattingProvider, getFormattingProviderRegistrySnapshot, regis
|
|
|
9
9
|
export { exists, mkdir, readDirWithFileTypes, readFile, remove, writeFile } from "./parts/FileSystem/FileSystem.js";
|
|
10
10
|
export { executeHoverProvider, getHoverProviderRegistrySnapshot, registerHoverProvider, resetHoverProviderRegistry } from "./parts/Hover/Hover.js";
|
|
11
11
|
export { executeSourceControlAcceptInput, executeSourceControlAdd, executeSourceControlDiscard, executeSourceControlGenerateCommitMessage, executeSourceControlGetChangedFiles, executeSourceControlGetFeatures, executeSourceControlGetFileBefore, executeSourceControlGetFileDecorations, executeSourceControlGetGroups, executeSourceControlIsActive, registerSourceControlProvider, resetSourceControlProviderRegistry, } from "./parts/SourceControl/SourceControl.js";
|
|
12
|
-
export { createViewInstance, dispatchViewEvent, disposeViewInstance, executeViewProvider, getViewRegistrySnapshot, registerView, resetViewRegistry, saveViewInstanceState, } from "./parts/ViewRegistry/ViewRegistry.js";
|
|
12
|
+
export { createViewInstance, dispatchViewEvent, disposeViewInstance, executeViewProvider, getViewRegistrySnapshot, renderViewInstance, registerView, resetViewRegistry, saveViewInstanceState, } from "./parts/ViewRegistry/ViewRegistry.js";
|
|
13
13
|
export { createOutputChannel, getOutputChannelRegistrySnapshot, resetOutputChannelRegistry } from "./parts/OutputChannel/OutputChannel.js";
|
|
14
14
|
export { getStatusBarItemProviderRegistrySnapshot, registerStatusBarItemProvider, resetStatusBarItemProviderRegistry, } from "./parts/StatusBar/StatusBar.js";
|
|
15
15
|
export { handleExtensionManagementMessagePort } from "./parts/HandleExtensionManagementMessagePort/HandleExtensionManagementMessagePort.js";
|
|
@@ -28,6 +28,8 @@ export declare const commandMap: {
|
|
|
28
28
|
'ExtensionApi.getOutputChannelRegistrySnapshot': () => import("../OutputChannelRegistrySnapshot/OutputChannelRegistrySnapshot.ts").OutputChannelRegistrySnapshot;
|
|
29
29
|
'ExtensionApi.getSourceControlProviderRegistrySnapshot': () => import("../SourceControlProviderRegistrySnapshot/SourceControlProviderRegistrySnapshot.ts").SourceControlProviderRegistrySnapshot;
|
|
30
30
|
'ExtensionApi.getStatusBarItems': () => readonly import("../StatusBarItem/StatusBarItem.ts").StatusBarItem[];
|
|
31
|
+
'ExtensionApi.getViewMenuEntries': (uid: number, menuId: string) => Promise<readonly import("../View/View.ts").MenuEntry[]>;
|
|
31
32
|
'ExtensionApi.getViewRegistrySnapshot': () => import("../View/View.ts").ViewRegistrySnapshot;
|
|
33
|
+
'ExtensionApi.renderViewInstance': (uid: number) => Promise<import("../View/View.ts").ViewRenderResult>;
|
|
32
34
|
'ExtensionApi.saveViewInstanceState': (uid: number) => Promise<unknown>;
|
|
33
35
|
};
|
|
@@ -27,6 +27,8 @@ export declare const commandMap: {
|
|
|
27
27
|
'ExtensionApi.getOutputChannelRegistrySnapshot': () => import("../OutputChannelRegistrySnapshot/OutputChannelRegistrySnapshot.ts").OutputChannelRegistrySnapshot;
|
|
28
28
|
'ExtensionApi.getSourceControlProviderRegistrySnapshot': () => import("../SourceControlProviderRegistrySnapshot/SourceControlProviderRegistrySnapshot.ts").SourceControlProviderRegistrySnapshot;
|
|
29
29
|
'ExtensionApi.getStatusBarItems': () => readonly import("../StatusBarItem/StatusBarItem.ts").StatusBarItem[];
|
|
30
|
+
'ExtensionApi.getViewMenuEntries': (uid: number, menuId: string) => Promise<readonly import("../View/View.ts").MenuEntry[]>;
|
|
30
31
|
'ExtensionApi.getViewRegistrySnapshot': () => import("../View/View.ts").ViewRegistrySnapshot;
|
|
32
|
+
'ExtensionApi.renderViewInstance': (uid: number) => Promise<import("../View/View.ts").ViewRenderResult>;
|
|
31
33
|
'ExtensionApi.saveViewInstanceState': (uid: number) => Promise<unknown>;
|
|
32
34
|
};
|
|
@@ -6,7 +6,7 @@ import { getStatusBarItems } from "../GetStatusBarItems/GetStatusBarItems.js";
|
|
|
6
6
|
import { executeHoverProvider, getHoverProviderRegistrySnapshot } from "../Hover/Hover.js";
|
|
7
7
|
import { getOutputChannelRegistrySnapshot } from "../OutputChannel/OutputChannel.js";
|
|
8
8
|
import { executeSourceControlAcceptInput, executeSourceControlAdd, executeSourceControlDiscard, executeSourceControlGenerateCommitMessage, executeSourceControlGetChangedFiles, executeSourceControlGetFeatures, executeSourceControlGetFileBefore, executeSourceControlGetFileDecorations, executeSourceControlGetGroups, executeSourceControlIsActive, getSourceControlProviderRegistrySnapshot, } from "../SourceControl/SourceControl.js";
|
|
9
|
-
import { createViewInstance, dispatchViewEvent, disposeViewInstance, executeViewProvider, getViewRegistrySnapshot, saveViewInstanceState, } from "../ViewRegistry/ViewRegistry.js";
|
|
9
|
+
import { createViewInstance, dispatchViewEvent, disposeViewInstance, executeViewProvider, getViewMenuEntries, getViewRegistrySnapshot, renderViewInstance, saveViewInstanceState, } from "../ViewRegistry/ViewRegistry.js";
|
|
10
10
|
export const commandMap = {
|
|
11
11
|
'ExtensionApi.createViewInstance': createViewInstance,
|
|
12
12
|
'ExtensionApi.dispatchViewEvent': dispatchViewEvent,
|
|
@@ -36,6 +36,8 @@ export const commandMap = {
|
|
|
36
36
|
'ExtensionApi.getOutputChannelRegistrySnapshot': getOutputChannelRegistrySnapshot,
|
|
37
37
|
'ExtensionApi.getSourceControlProviderRegistrySnapshot': getSourceControlProviderRegistrySnapshot,
|
|
38
38
|
'ExtensionApi.getStatusBarItems': getStatusBarItems,
|
|
39
|
+
'ExtensionApi.getViewMenuEntries': getViewMenuEntries,
|
|
39
40
|
'ExtensionApi.getViewRegistrySnapshot': getViewRegistrySnapshot,
|
|
41
|
+
'ExtensionApi.renderViewInstance': renderViewInstance,
|
|
40
42
|
'ExtensionApi.saveViewInstanceState': saveViewInstanceState,
|
|
41
43
|
};
|
package/extension-api/dist/parts/ExtensionApiWorkerCommandMap/ExtensionApiWorkerCommandMap.d.ts
CHANGED
|
@@ -29,6 +29,8 @@ export declare const commandMap: {
|
|
|
29
29
|
'ExtensionApi.getOutputChannelRegistrySnapshot': () => import("../OutputChannelRegistrySnapshot/OutputChannelRegistrySnapshot.ts").OutputChannelRegistrySnapshot;
|
|
30
30
|
'ExtensionApi.getSourceControlProviderRegistrySnapshot': () => import("../SourceControlProviderRegistrySnapshot/SourceControlProviderRegistrySnapshot.ts").SourceControlProviderRegistrySnapshot;
|
|
31
31
|
'ExtensionApi.getStatusBarItems': () => readonly import("../StatusBarItem/StatusBarItem.ts").StatusBarItem[];
|
|
32
|
+
'ExtensionApi.getViewMenuEntries': (uid: number, menuId: string) => Promise<readonly import("../View/View.ts").MenuEntry[]>;
|
|
32
33
|
'ExtensionApi.getViewRegistrySnapshot': () => import("../View/View.ts").ViewRegistrySnapshot;
|
|
34
|
+
'ExtensionApi.renderViewInstance': (uid: number) => Promise<import("../View/View.ts").ViewRenderResult>;
|
|
33
35
|
'ExtensionApi.saveViewInstanceState': (uid: number) => Promise<unknown>;
|
|
34
36
|
};
|