@lvce-editor/extension-host-worker 8.35.0 → 8.37.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 +71 -8
- package/dist/extension-api/parts/ExtensionApiCommandMap/ExtensionApiCommandMap.js +2 -0
- package/dist/extension-api/parts/ViewRegistry/ViewRegistry.js +71 -8
- package/extension-api/dist/index.d.ts +1 -1
- package/extension-api/dist/parts/CommandMap/CommandMap.d.ts +1 -0
- package/extension-api/dist/parts/ExtensionApiCommandMap/ExtensionApiCommandMap.d.ts +1 -0
- package/extension-api/dist/parts/ExtensionApiCommandMap/ExtensionApiCommandMap.js +2 -1
- package/extension-api/dist/parts/ExtensionApiWorkerCommandMap/ExtensionApiWorkerCommandMap.d.ts +1 -0
- package/extension-api/dist/parts/View/View.d.ts +9 -0
- package/extension-api/dist/parts/ViewRegistry/ViewRegistry.d.ts +2 -1
- package/extension-api/dist/parts/ViewRegistry/ViewRegistry.js +70 -8
- package/extension-api/package.json +1 -1
- package/extension-api/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -2536,6 +2536,26 @@ var normalizeMenuEntries = (entries) => {
|
|
|
2536
2536
|
}
|
|
2537
2537
|
return entries.map(normalizeMenuEntry);
|
|
2538
2538
|
};
|
|
2539
|
+
var normalizeViewAction = (action, index) => {
|
|
2540
|
+
if (!action || typeof action !== "object" || Array.isArray(action)) {
|
|
2541
|
+
throw new ExtensionApiError(`view action ${index} must be an object`);
|
|
2542
|
+
}
|
|
2543
|
+
const viewAction = action;
|
|
2544
|
+
assertString(viewAction.title, `view action ${index} is missing title`);
|
|
2545
|
+
assertString(viewAction.icon, `view action ${index} is missing icon`);
|
|
2546
|
+
assertString(viewAction.command, `view action ${index} is missing command`);
|
|
2547
|
+
return {
|
|
2548
|
+
command: viewAction.command,
|
|
2549
|
+
icon: viewAction.icon,
|
|
2550
|
+
title: viewAction.title
|
|
2551
|
+
};
|
|
2552
|
+
};
|
|
2553
|
+
var normalizeViewActions = (actions) => {
|
|
2554
|
+
if (!Array.isArray(actions)) {
|
|
2555
|
+
throw new ExtensionApiError("view actions must be an array");
|
|
2556
|
+
}
|
|
2557
|
+
return actions.map(normalizeViewAction);
|
|
2558
|
+
};
|
|
2539
2559
|
var renderPatches = async (uid, instance) => {
|
|
2540
2560
|
const oldDom = renderedDoms[uid] || [];
|
|
2541
2561
|
const newDom = await renderDom(instance);
|
|
@@ -2571,14 +2591,23 @@ var isSameContext = (oldContext, newContext) => {
|
|
|
2571
2591
|
}
|
|
2572
2592
|
return true;
|
|
2573
2593
|
};
|
|
2594
|
+
var unchangedContext = {
|
|
2595
|
+
changed: false,
|
|
2596
|
+
newContext: {},
|
|
2597
|
+
oldContext: {}
|
|
2598
|
+
};
|
|
2574
2599
|
var maybeNotifyContextChanged = async (uid, viewId, instance) => {
|
|
2575
2600
|
if (typeof instance.getContext !== "function") {
|
|
2576
|
-
return;
|
|
2601
|
+
return unchangedContext;
|
|
2577
2602
|
}
|
|
2578
2603
|
const oldContext = contexts[uid] || {};
|
|
2579
2604
|
const newContext = normalizeContext(instance.getContext());
|
|
2580
2605
|
if (isSameContext(oldContext, newContext)) {
|
|
2581
|
-
return
|
|
2606
|
+
return {
|
|
2607
|
+
changed: false,
|
|
2608
|
+
newContext,
|
|
2609
|
+
oldContext
|
|
2610
|
+
};
|
|
2582
2611
|
}
|
|
2583
2612
|
if (Object.keys(newContext).length === 0) {
|
|
2584
2613
|
delete contexts[uid];
|
|
@@ -2586,6 +2615,31 @@ var maybeNotifyContextChanged = async (uid, viewId, instance) => {
|
|
|
2586
2615
|
contexts[uid] = newContext;
|
|
2587
2616
|
}
|
|
2588
2617
|
await ExtensionManagementWorker_exports.invoke("Extensions.handleViewContextChange", uid, viewId, newContext);
|
|
2618
|
+
return {
|
|
2619
|
+
changed: true,
|
|
2620
|
+
newContext,
|
|
2621
|
+
oldContext
|
|
2622
|
+
};
|
|
2623
|
+
};
|
|
2624
|
+
var renderFocus = async (instance, contextChange) => {
|
|
2625
|
+
if (!contextChange.changed || typeof instance.renderFocus !== "function") {
|
|
2626
|
+
return "";
|
|
2627
|
+
}
|
|
2628
|
+
const focusSelector = await instance.renderFocus(contextChange.oldContext, contextChange.newContext);
|
|
2629
|
+
if (typeof focusSelector !== "string") {
|
|
2630
|
+
throw new ExtensionApiError("view renderFocus result must be a string");
|
|
2631
|
+
}
|
|
2632
|
+
return focusSelector;
|
|
2633
|
+
};
|
|
2634
|
+
var withFocusSelector = async (result, instance, contextChange) => {
|
|
2635
|
+
const focusSelector = await renderFocus(instance, contextChange);
|
|
2636
|
+
if (!focusSelector) {
|
|
2637
|
+
return result;
|
|
2638
|
+
}
|
|
2639
|
+
return {
|
|
2640
|
+
...result,
|
|
2641
|
+
focusSelector
|
|
2642
|
+
};
|
|
2589
2643
|
};
|
|
2590
2644
|
var maybeClearContext = async (uid, viewId) => {
|
|
2591
2645
|
if (!contexts[uid]) {
|
|
@@ -2621,11 +2675,12 @@ var createViewInstance = async (viewId, uid, context) => {
|
|
|
2621
2675
|
contextViewIds[uid] = viewId;
|
|
2622
2676
|
const dom = await renderDom(instance);
|
|
2623
2677
|
renderedDoms[uid] = dom;
|
|
2624
|
-
|
|
2625
|
-
return {
|
|
2678
|
+
const result = {
|
|
2626
2679
|
dom,
|
|
2627
2680
|
type: "setDom"
|
|
2628
2681
|
};
|
|
2682
|
+
const contextChange = await maybeNotifyContextChanged(uid, viewId, instance);
|
|
2683
|
+
return withFocusSelector(result, instance, contextChange);
|
|
2629
2684
|
};
|
|
2630
2685
|
var dispatchViewEvent = async (uid, event) => {
|
|
2631
2686
|
const instance = getVirtualDomInstance(uid);
|
|
@@ -2633,14 +2688,14 @@ var dispatchViewEvent = async (uid, event) => {
|
|
|
2633
2688
|
await instance.handleEvent(event);
|
|
2634
2689
|
}
|
|
2635
2690
|
const result = await renderPatches(uid, instance);
|
|
2636
|
-
await maybeNotifyContextChanged(uid, contextViewIds[uid], instance);
|
|
2637
|
-
return result;
|
|
2691
|
+
const contextChange = await maybeNotifyContextChanged(uid, contextViewIds[uid], instance);
|
|
2692
|
+
return withFocusSelector(result, instance, contextChange);
|
|
2638
2693
|
};
|
|
2639
2694
|
var renderViewInstance = async (uid) => {
|
|
2640
2695
|
const instance = getVirtualDomInstance(uid);
|
|
2641
2696
|
const result = await renderPatches(uid, instance);
|
|
2642
|
-
await maybeNotifyContextChanged(uid, contextViewIds[uid], instance);
|
|
2643
|
-
return result;
|
|
2697
|
+
const contextChange = await maybeNotifyContextChanged(uid, contextViewIds[uid], instance);
|
|
2698
|
+
return withFocusSelector(result, instance, contextChange);
|
|
2644
2699
|
};
|
|
2645
2700
|
var disposeViewInstance = async (uid) => {
|
|
2646
2701
|
const instance = instances[uid];
|
|
@@ -2667,6 +2722,13 @@ var getViewMenuEntries = async (uid, menuId) => {
|
|
|
2667
2722
|
}
|
|
2668
2723
|
return normalizeMenuEntries(await instance.getMenuEntries(menuId));
|
|
2669
2724
|
};
|
|
2725
|
+
var getViewActions = async (uid) => {
|
|
2726
|
+
const instance = getVirtualDomInstance(uid);
|
|
2727
|
+
if (typeof instance.renderActions !== "function") {
|
|
2728
|
+
return [];
|
|
2729
|
+
}
|
|
2730
|
+
return normalizeViewActions(await instance.renderActions());
|
|
2731
|
+
};
|
|
2670
2732
|
var getViewRegistrySnapshot = () => {
|
|
2671
2733
|
return {
|
|
2672
2734
|
views: Object.values(views).map(toRegisteredView)
|
|
@@ -2720,6 +2782,7 @@ var commandMap = {
|
|
|
2720
2782
|
"ExtensionApi.getOutputChannelRegistrySnapshot": getOutputChannelRegistrySnapshot,
|
|
2721
2783
|
"ExtensionApi.getSourceControlProviderRegistrySnapshot": getSourceControlProviderRegistrySnapshot,
|
|
2722
2784
|
"ExtensionApi.getStatusBarItems": getStatusBarItems,
|
|
2785
|
+
"ExtensionApi.getViewActions": getViewActions,
|
|
2723
2786
|
"ExtensionApi.getViewMenuEntries": getViewMenuEntries,
|
|
2724
2787
|
"ExtensionApi.getViewRegistrySnapshot": getViewRegistrySnapshot,
|
|
2725
2788
|
"ExtensionApi.renderViewInstance": renderViewInstance,
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
dispatchViewEvent,
|
|
24
24
|
disposeViewInstance,
|
|
25
25
|
executeViewProvider,
|
|
26
|
+
getViewActions,
|
|
26
27
|
getViewMenuEntries,
|
|
27
28
|
getViewRegistrySnapshot,
|
|
28
29
|
renderViewInstance,
|
|
@@ -57,6 +58,7 @@ const commandMap = {
|
|
|
57
58
|
"ExtensionApi.getOutputChannelRegistrySnapshot": getOutputChannelRegistrySnapshot,
|
|
58
59
|
"ExtensionApi.getSourceControlProviderRegistrySnapshot": getSourceControlProviderRegistrySnapshot,
|
|
59
60
|
"ExtensionApi.getStatusBarItems": getStatusBarItems,
|
|
61
|
+
"ExtensionApi.getViewActions": getViewActions,
|
|
60
62
|
"ExtensionApi.getViewMenuEntries": getViewMenuEntries,
|
|
61
63
|
"ExtensionApi.getViewRegistrySnapshot": getViewRegistrySnapshot,
|
|
62
64
|
"ExtensionApi.renderViewInstance": renderViewInstance,
|
|
@@ -147,6 +147,26 @@ const normalizeMenuEntries = (entries) => {
|
|
|
147
147
|
}
|
|
148
148
|
return entries.map(normalizeMenuEntry);
|
|
149
149
|
};
|
|
150
|
+
const normalizeViewAction = (action, index) => {
|
|
151
|
+
if (!action || typeof action !== "object" || Array.isArray(action)) {
|
|
152
|
+
throw new ExtensionApiError(`view action ${index} must be an object`);
|
|
153
|
+
}
|
|
154
|
+
const viewAction = action;
|
|
155
|
+
assertString(viewAction.title, `view action ${index} is missing title`);
|
|
156
|
+
assertString(viewAction.icon, `view action ${index} is missing icon`);
|
|
157
|
+
assertString(viewAction.command, `view action ${index} is missing command`);
|
|
158
|
+
return {
|
|
159
|
+
command: viewAction.command,
|
|
160
|
+
icon: viewAction.icon,
|
|
161
|
+
title: viewAction.title
|
|
162
|
+
};
|
|
163
|
+
};
|
|
164
|
+
const normalizeViewActions = (actions) => {
|
|
165
|
+
if (!Array.isArray(actions)) {
|
|
166
|
+
throw new ExtensionApiError("view actions must be an array");
|
|
167
|
+
}
|
|
168
|
+
return actions.map(normalizeViewAction);
|
|
169
|
+
};
|
|
150
170
|
const renderPatches = async (uid, instance) => {
|
|
151
171
|
const oldDom = renderedDoms[uid] || [];
|
|
152
172
|
const newDom = await renderDom(instance);
|
|
@@ -182,14 +202,23 @@ const isSameContext = (oldContext, newContext) => {
|
|
|
182
202
|
}
|
|
183
203
|
return true;
|
|
184
204
|
};
|
|
205
|
+
const unchangedContext = {
|
|
206
|
+
changed: false,
|
|
207
|
+
newContext: {},
|
|
208
|
+
oldContext: {}
|
|
209
|
+
};
|
|
185
210
|
const maybeNotifyContextChanged = async (uid, viewId, instance) => {
|
|
186
211
|
if (typeof instance.getContext !== "function") {
|
|
187
|
-
return;
|
|
212
|
+
return unchangedContext;
|
|
188
213
|
}
|
|
189
214
|
const oldContext = contexts[uid] || {};
|
|
190
215
|
const newContext = normalizeContext(instance.getContext());
|
|
191
216
|
if (isSameContext(oldContext, newContext)) {
|
|
192
|
-
return
|
|
217
|
+
return {
|
|
218
|
+
changed: false,
|
|
219
|
+
newContext,
|
|
220
|
+
oldContext
|
|
221
|
+
};
|
|
193
222
|
}
|
|
194
223
|
if (Object.keys(newContext).length === 0) {
|
|
195
224
|
delete contexts[uid];
|
|
@@ -197,6 +226,31 @@ const maybeNotifyContextChanged = async (uid, viewId, instance) => {
|
|
|
197
226
|
contexts[uid] = newContext;
|
|
198
227
|
}
|
|
199
228
|
await ExtensionManagementWorker.invoke("Extensions.handleViewContextChange", uid, viewId, newContext);
|
|
229
|
+
return {
|
|
230
|
+
changed: true,
|
|
231
|
+
newContext,
|
|
232
|
+
oldContext
|
|
233
|
+
};
|
|
234
|
+
};
|
|
235
|
+
const renderFocus = async (instance, contextChange) => {
|
|
236
|
+
if (!contextChange.changed || typeof instance.renderFocus !== "function") {
|
|
237
|
+
return "";
|
|
238
|
+
}
|
|
239
|
+
const focusSelector = await instance.renderFocus(contextChange.oldContext, contextChange.newContext);
|
|
240
|
+
if (typeof focusSelector !== "string") {
|
|
241
|
+
throw new ExtensionApiError("view renderFocus result must be a string");
|
|
242
|
+
}
|
|
243
|
+
return focusSelector;
|
|
244
|
+
};
|
|
245
|
+
const withFocusSelector = async (result, instance, contextChange) => {
|
|
246
|
+
const focusSelector = await renderFocus(instance, contextChange);
|
|
247
|
+
if (!focusSelector) {
|
|
248
|
+
return result;
|
|
249
|
+
}
|
|
250
|
+
return {
|
|
251
|
+
...result,
|
|
252
|
+
focusSelector
|
|
253
|
+
};
|
|
200
254
|
};
|
|
201
255
|
const maybeClearContext = async (uid, viewId) => {
|
|
202
256
|
if (!contexts[uid]) {
|
|
@@ -232,11 +286,12 @@ const createViewInstance = async (viewId, uid, context) => {
|
|
|
232
286
|
contextViewIds[uid] = viewId;
|
|
233
287
|
const dom = await renderDom(instance);
|
|
234
288
|
renderedDoms[uid] = dom;
|
|
235
|
-
|
|
236
|
-
return {
|
|
289
|
+
const result = {
|
|
237
290
|
dom,
|
|
238
291
|
type: "setDom"
|
|
239
292
|
};
|
|
293
|
+
const contextChange = await maybeNotifyContextChanged(uid, viewId, instance);
|
|
294
|
+
return withFocusSelector(result, instance, contextChange);
|
|
240
295
|
};
|
|
241
296
|
const dispatchViewEvent = async (uid, event) => {
|
|
242
297
|
const instance = getVirtualDomInstance(uid);
|
|
@@ -244,14 +299,14 @@ const dispatchViewEvent = async (uid, event) => {
|
|
|
244
299
|
await instance.handleEvent(event);
|
|
245
300
|
}
|
|
246
301
|
const result = await renderPatches(uid, instance);
|
|
247
|
-
await maybeNotifyContextChanged(uid, contextViewIds[uid], instance);
|
|
248
|
-
return result;
|
|
302
|
+
const contextChange = await maybeNotifyContextChanged(uid, contextViewIds[uid], instance);
|
|
303
|
+
return withFocusSelector(result, instance, contextChange);
|
|
249
304
|
};
|
|
250
305
|
const renderViewInstance = async (uid) => {
|
|
251
306
|
const instance = getVirtualDomInstance(uid);
|
|
252
307
|
const result = await renderPatches(uid, instance);
|
|
253
|
-
await maybeNotifyContextChanged(uid, contextViewIds[uid], instance);
|
|
254
|
-
return result;
|
|
308
|
+
const contextChange = await maybeNotifyContextChanged(uid, contextViewIds[uid], instance);
|
|
309
|
+
return withFocusSelector(result, instance, contextChange);
|
|
255
310
|
};
|
|
256
311
|
const disposeViewInstance = async (uid) => {
|
|
257
312
|
const instance = instances[uid];
|
|
@@ -278,6 +333,13 @@ const getViewMenuEntries = async (uid, menuId) => {
|
|
|
278
333
|
}
|
|
279
334
|
return normalizeMenuEntries(await instance.getMenuEntries(menuId));
|
|
280
335
|
};
|
|
336
|
+
const getViewActions = async (uid) => {
|
|
337
|
+
const instance = getVirtualDomInstance(uid);
|
|
338
|
+
if (typeof instance.renderActions !== "function") {
|
|
339
|
+
return [];
|
|
340
|
+
}
|
|
341
|
+
return normalizeViewActions(await instance.renderActions());
|
|
342
|
+
};
|
|
281
343
|
const getViewRegistrySnapshot = () => {
|
|
282
344
|
return {
|
|
283
345
|
views: Object.values(views).map(toRegisteredView)
|
|
@@ -305,6 +367,7 @@ export {
|
|
|
305
367
|
dispatchViewEvent,
|
|
306
368
|
disposeViewInstance,
|
|
307
369
|
executeViewProvider,
|
|
370
|
+
getViewActions,
|
|
308
371
|
getViewMenuEntries,
|
|
309
372
|
getViewRegistrySnapshot,
|
|
310
373
|
registerView,
|
|
@@ -12,7 +12,7 @@ export { executeSourceControlAcceptInput, executeSourceControlAdd, executeSource
|
|
|
12
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, MenuEntry, ViewRegistrySnapshot, ViewRenderResult, VirtualDomViewInstance, } from './parts/View/View.ts';
|
|
15
|
+
export type { RegisteredView, View, ViewAction, 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';
|
|
@@ -28,6 +28,7 @@ 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.getViewActions': (uid: number) => Promise<readonly import("../View/View.ts").ViewAction[]>;
|
|
31
32
|
'ExtensionApi.getViewMenuEntries': (uid: number, menuId: string) => Promise<readonly import("../View/View.ts").MenuEntry[]>;
|
|
32
33
|
'ExtensionApi.getViewRegistrySnapshot': () => import("../View/View.ts").ViewRegistrySnapshot;
|
|
33
34
|
'ExtensionApi.renderViewInstance': (uid: number) => Promise<import("../View/View.ts").ViewRenderResult>;
|
|
@@ -27,6 +27,7 @@ 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.getViewActions': (uid: number) => Promise<readonly import("../View/View.ts").ViewAction[]>;
|
|
30
31
|
'ExtensionApi.getViewMenuEntries': (uid: number, menuId: string) => Promise<readonly import("../View/View.ts").MenuEntry[]>;
|
|
31
32
|
'ExtensionApi.getViewRegistrySnapshot': () => import("../View/View.ts").ViewRegistrySnapshot;
|
|
32
33
|
'ExtensionApi.renderViewInstance': (uid: number) => Promise<import("../View/View.ts").ViewRenderResult>;
|
|
@@ -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, getViewMenuEntries, getViewRegistrySnapshot, renderViewInstance, saveViewInstanceState, } from "../ViewRegistry/ViewRegistry.js";
|
|
9
|
+
import { createViewInstance, dispatchViewEvent, disposeViewInstance, executeViewProvider, getViewActions, 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,7 @@ export const commandMap = {
|
|
|
36
36
|
'ExtensionApi.getOutputChannelRegistrySnapshot': getOutputChannelRegistrySnapshot,
|
|
37
37
|
'ExtensionApi.getSourceControlProviderRegistrySnapshot': getSourceControlProviderRegistrySnapshot,
|
|
38
38
|
'ExtensionApi.getStatusBarItems': getStatusBarItems,
|
|
39
|
+
'ExtensionApi.getViewActions': getViewActions,
|
|
39
40
|
'ExtensionApi.getViewMenuEntries': getViewMenuEntries,
|
|
40
41
|
'ExtensionApi.getViewRegistrySnapshot': getViewRegistrySnapshot,
|
|
41
42
|
'ExtensionApi.renderViewInstance': renderViewInstance,
|
package/extension-api/dist/parts/ExtensionApiWorkerCommandMap/ExtensionApiWorkerCommandMap.d.ts
CHANGED
|
@@ -29,6 +29,7 @@ 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.getViewActions': (uid: number) => Promise<readonly import("../View/View.ts").ViewAction[]>;
|
|
32
33
|
'ExtensionApi.getViewMenuEntries': (uid: number, menuId: string) => Promise<readonly import("../View/View.ts").MenuEntry[]>;
|
|
33
34
|
'ExtensionApi.getViewRegistrySnapshot': () => import("../View/View.ts").ViewRegistrySnapshot;
|
|
34
35
|
'ExtensionApi.renderViewInstance': (uid: number) => Promise<import("../View/View.ts").ViewRenderResult>;
|
|
@@ -21,6 +21,11 @@ export interface MenuEntry {
|
|
|
21
21
|
readonly id: string;
|
|
22
22
|
readonly label: string;
|
|
23
23
|
}
|
|
24
|
+
export interface ViewAction {
|
|
25
|
+
readonly command: string;
|
|
26
|
+
readonly icon: string;
|
|
27
|
+
readonly title: string;
|
|
28
|
+
}
|
|
24
29
|
export interface DomEventListener {
|
|
25
30
|
readonly capture?: boolean;
|
|
26
31
|
readonly name: string | number;
|
|
@@ -35,6 +40,8 @@ export interface VirtualDomViewInstance {
|
|
|
35
40
|
readonly getMenuEntries?: (menuId: string) => readonly MenuEntry[] | Promise<readonly MenuEntry[]>;
|
|
36
41
|
readonly handleEvent?: (event: ViewEvent) => unknown;
|
|
37
42
|
readonly render: () => readonly VirtualDomNode[] | Promise<readonly VirtualDomNode[]>;
|
|
43
|
+
readonly renderActions?: () => readonly ViewAction[] | Promise<readonly ViewAction[]>;
|
|
44
|
+
readonly renderFocus?: (oldContext: Readonly<Record<string, boolean>>, newContext: Readonly<Record<string, boolean>>) => string | Promise<string>;
|
|
38
45
|
readonly saveState?: () => unknown;
|
|
39
46
|
}
|
|
40
47
|
export interface View {
|
|
@@ -61,9 +68,11 @@ export interface ViewRegistrySnapshot {
|
|
|
61
68
|
}
|
|
62
69
|
export interface ViewRenderResultDom {
|
|
63
70
|
readonly dom: readonly VirtualDomNode[];
|
|
71
|
+
readonly focusSelector?: string;
|
|
64
72
|
readonly type: 'setDom';
|
|
65
73
|
}
|
|
66
74
|
export interface ViewRenderResultPatches {
|
|
75
|
+
readonly focusSelector?: string;
|
|
67
76
|
readonly patches: readonly unknown[];
|
|
68
77
|
readonly type: 'setPatches';
|
|
69
78
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Disposable } from '../Disposable/Disposable.ts';
|
|
2
|
-
import type { MenuEntry, View, ViewContext, ViewEvent, ViewRegistrySnapshot, ViewRenderResult } from '../View/View.ts';
|
|
2
|
+
import type { MenuEntry, View, ViewAction, ViewContext, ViewEvent, ViewRegistrySnapshot, ViewRenderResult } from '../View/View.ts';
|
|
3
3
|
export declare const registerView: (view: View) => Disposable;
|
|
4
4
|
export declare const executeViewProvider: (id: string) => unknown;
|
|
5
5
|
export declare const createViewInstance: (viewId: string, uid: number, context?: ViewContext) => Promise<ViewRenderResult>;
|
|
@@ -8,5 +8,6 @@ export declare const renderViewInstance: (uid: number) => Promise<ViewRenderResu
|
|
|
8
8
|
export declare const disposeViewInstance: (uid: number) => Promise<void>;
|
|
9
9
|
export declare const saveViewInstanceState: (uid: number) => Promise<unknown>;
|
|
10
10
|
export declare const getViewMenuEntries: (uid: number, menuId: string) => Promise<readonly MenuEntry[]>;
|
|
11
|
+
export declare const getViewActions: (uid: number) => Promise<readonly ViewAction[]>;
|
|
11
12
|
export declare const getViewRegistrySnapshot: () => ViewRegistrySnapshot;
|
|
12
13
|
export declare const resetViewRegistry: () => void;
|
|
@@ -147,6 +147,26 @@ const normalizeMenuEntries = (entries) => {
|
|
|
147
147
|
}
|
|
148
148
|
return entries.map(normalizeMenuEntry);
|
|
149
149
|
};
|
|
150
|
+
const normalizeViewAction = (action, index) => {
|
|
151
|
+
if (!action || typeof action !== 'object' || Array.isArray(action)) {
|
|
152
|
+
throw new ExtensionApiError(`view action ${index} must be an object`);
|
|
153
|
+
}
|
|
154
|
+
const viewAction = action;
|
|
155
|
+
assertString(viewAction.title, `view action ${index} is missing title`);
|
|
156
|
+
assertString(viewAction.icon, `view action ${index} is missing icon`);
|
|
157
|
+
assertString(viewAction.command, `view action ${index} is missing command`);
|
|
158
|
+
return {
|
|
159
|
+
command: viewAction.command,
|
|
160
|
+
icon: viewAction.icon,
|
|
161
|
+
title: viewAction.title,
|
|
162
|
+
};
|
|
163
|
+
};
|
|
164
|
+
const normalizeViewActions = (actions) => {
|
|
165
|
+
if (!Array.isArray(actions)) {
|
|
166
|
+
throw new ExtensionApiError('view actions must be an array');
|
|
167
|
+
}
|
|
168
|
+
return actions.map(normalizeViewAction);
|
|
169
|
+
};
|
|
150
170
|
const renderPatches = async (uid, instance) => {
|
|
151
171
|
const oldDom = renderedDoms[uid] || [];
|
|
152
172
|
const newDom = await renderDom(instance);
|
|
@@ -182,14 +202,23 @@ const isSameContext = (oldContext, newContext) => {
|
|
|
182
202
|
}
|
|
183
203
|
return true;
|
|
184
204
|
};
|
|
205
|
+
const unchangedContext = {
|
|
206
|
+
changed: false,
|
|
207
|
+
newContext: {},
|
|
208
|
+
oldContext: {},
|
|
209
|
+
};
|
|
185
210
|
const maybeNotifyContextChanged = async (uid, viewId, instance) => {
|
|
186
211
|
if (typeof instance.getContext !== 'function') {
|
|
187
|
-
return;
|
|
212
|
+
return unchangedContext;
|
|
188
213
|
}
|
|
189
214
|
const oldContext = contexts[uid] || {};
|
|
190
215
|
const newContext = normalizeContext(instance.getContext());
|
|
191
216
|
if (isSameContext(oldContext, newContext)) {
|
|
192
|
-
return
|
|
217
|
+
return {
|
|
218
|
+
changed: false,
|
|
219
|
+
newContext,
|
|
220
|
+
oldContext,
|
|
221
|
+
};
|
|
193
222
|
}
|
|
194
223
|
if (Object.keys(newContext).length === 0) {
|
|
195
224
|
delete contexts[uid];
|
|
@@ -198,6 +227,31 @@ const maybeNotifyContextChanged = async (uid, viewId, instance) => {
|
|
|
198
227
|
contexts[uid] = newContext;
|
|
199
228
|
}
|
|
200
229
|
await ExtensionManagementWorker.invoke('Extensions.handleViewContextChange', uid, viewId, newContext);
|
|
230
|
+
return {
|
|
231
|
+
changed: true,
|
|
232
|
+
newContext,
|
|
233
|
+
oldContext,
|
|
234
|
+
};
|
|
235
|
+
};
|
|
236
|
+
const renderFocus = async (instance, contextChange) => {
|
|
237
|
+
if (!contextChange.changed || typeof instance.renderFocus !== 'function') {
|
|
238
|
+
return '';
|
|
239
|
+
}
|
|
240
|
+
const focusSelector = await instance.renderFocus(contextChange.oldContext, contextChange.newContext);
|
|
241
|
+
if (typeof focusSelector !== 'string') {
|
|
242
|
+
throw new ExtensionApiError('view renderFocus result must be a string');
|
|
243
|
+
}
|
|
244
|
+
return focusSelector;
|
|
245
|
+
};
|
|
246
|
+
const withFocusSelector = async (result, instance, contextChange) => {
|
|
247
|
+
const focusSelector = await renderFocus(instance, contextChange);
|
|
248
|
+
if (!focusSelector) {
|
|
249
|
+
return result;
|
|
250
|
+
}
|
|
251
|
+
return {
|
|
252
|
+
...result,
|
|
253
|
+
focusSelector,
|
|
254
|
+
};
|
|
201
255
|
};
|
|
202
256
|
const maybeClearContext = async (uid, viewId) => {
|
|
203
257
|
if (!contexts[uid]) {
|
|
@@ -233,11 +287,12 @@ export const createViewInstance = async (viewId, uid, context) => {
|
|
|
233
287
|
contextViewIds[uid] = viewId;
|
|
234
288
|
const dom = await renderDom(instance);
|
|
235
289
|
renderedDoms[uid] = dom;
|
|
236
|
-
|
|
237
|
-
return {
|
|
290
|
+
const result = {
|
|
238
291
|
dom,
|
|
239
292
|
type: 'setDom',
|
|
240
293
|
};
|
|
294
|
+
const contextChange = await maybeNotifyContextChanged(uid, viewId, instance);
|
|
295
|
+
return withFocusSelector(result, instance, contextChange);
|
|
241
296
|
};
|
|
242
297
|
export const dispatchViewEvent = async (uid, event) => {
|
|
243
298
|
const instance = getVirtualDomInstance(uid);
|
|
@@ -245,14 +300,14 @@ export const dispatchViewEvent = async (uid, event) => {
|
|
|
245
300
|
await instance.handleEvent(event);
|
|
246
301
|
}
|
|
247
302
|
const result = await renderPatches(uid, instance);
|
|
248
|
-
await maybeNotifyContextChanged(uid, contextViewIds[uid], instance);
|
|
249
|
-
return result;
|
|
303
|
+
const contextChange = await maybeNotifyContextChanged(uid, contextViewIds[uid], instance);
|
|
304
|
+
return withFocusSelector(result, instance, contextChange);
|
|
250
305
|
};
|
|
251
306
|
export const renderViewInstance = async (uid) => {
|
|
252
307
|
const instance = getVirtualDomInstance(uid);
|
|
253
308
|
const result = await renderPatches(uid, instance);
|
|
254
|
-
await maybeNotifyContextChanged(uid, contextViewIds[uid], instance);
|
|
255
|
-
return result;
|
|
309
|
+
const contextChange = await maybeNotifyContextChanged(uid, contextViewIds[uid], instance);
|
|
310
|
+
return withFocusSelector(result, instance, contextChange);
|
|
256
311
|
};
|
|
257
312
|
export const disposeViewInstance = async (uid) => {
|
|
258
313
|
const instance = instances[uid];
|
|
@@ -279,6 +334,13 @@ export const getViewMenuEntries = async (uid, menuId) => {
|
|
|
279
334
|
}
|
|
280
335
|
return normalizeMenuEntries(await instance.getMenuEntries(menuId));
|
|
281
336
|
};
|
|
337
|
+
export const getViewActions = async (uid) => {
|
|
338
|
+
const instance = getVirtualDomInstance(uid);
|
|
339
|
+
if (typeof instance.renderActions !== 'function') {
|
|
340
|
+
return [];
|
|
341
|
+
}
|
|
342
|
+
return normalizeViewActions(await instance.renderActions());
|
|
343
|
+
};
|
|
282
344
|
export const getViewRegistrySnapshot = () => {
|
|
283
345
|
return {
|
|
284
346
|
views: Object.values(views).map(toRegisteredView),
|