@dimina-kit/devtools 0.3.2-dev.20260522110734 → 0.3.2-dev.20260522142649
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/README.md +90 -155
- package/dist/main/api.d.ts +3 -11
- package/dist/main/api.js +2 -13
- package/dist/main/app/app.d.ts +14 -1
- package/dist/main/app/app.js +93 -2
- package/dist/main/index.bundle.js +140 -52
- package/dist/main/ipc/app.d.ts +1 -1
- package/dist/main/ipc/app.js +3 -0
- package/dist/main/ipc/simulator.d.ts +1 -1
- package/dist/main/ipc/simulator.js +2 -3
- package/dist/main/ipc/toolbar.d.ts +1 -1
- package/dist/main/ipc/toolbar.js +14 -4
- package/dist/main/services/layout/index.d.ts +4 -10
- package/dist/main/services/layout/index.js +11 -19
- package/dist/main/services/module.d.ts +1 -2
- package/dist/main/services/simulator/custom-apis.d.ts +0 -1
- package/dist/main/services/simulator/custom-apis.js +0 -1
- package/dist/main/services/toolbar/toolbar-store.d.ts +23 -0
- package/dist/main/services/toolbar/toolbar-store.js +23 -0
- package/dist/main/services/views/view-manager.d.ts +6 -0
- package/dist/main/services/views/view-manager.js +6 -3
- package/dist/main/services/workbench-context.d.ts +40 -14
- package/dist/main/services/workbench-context.js +6 -1
- package/dist/main/utils/disposable.d.ts +5 -0
- package/dist/main/utils/disposable.js +7 -0
- package/dist/main/utils/ipc-registry.js +5 -1
- package/dist/main/utils/sender-policy.d.ts +4 -1
- package/dist/main/utils/sender-policy.js +6 -0
- package/dist/preload/runtime/custom-apis.js +72 -1
- package/dist/preload/windows/simulator.js +41 -1
- package/dist/renderer/assets/index-4lkyF644.js +46 -0
- package/dist/renderer/assets/{input-CoWcfa8u.js → input-D4byFOLS.js} +2 -2
- package/dist/renderer/assets/{ipc-transport-Cd2xPrsa.js → ipc-transport-BzPzxPwf.js} +2 -2
- package/dist/renderer/assets/{popover-Nq5gT9DO.js → popover-cxKrg_os.js} +2 -2
- package/dist/renderer/assets/{select-By5KH-UG.js → select-BgSkkdHW.js} +2 -2
- package/dist/renderer/assets/{settings-api-Do0_Smq1.js → settings-api-BXCw9vOZ.js} +2 -2
- package/dist/renderer/assets/{settings-Dj_N70qR.js → settings-oD2K1jdT.js} +2 -2
- package/dist/renderer/assets/{workbenchSettings-CazSLGYt.js → workbenchSettings-CTNBpTft.js} +2 -2
- package/dist/renderer/entries/main/index.html +4 -4
- package/dist/renderer/entries/popover/index.html +4 -4
- package/dist/renderer/entries/settings/index.html +4 -4
- package/dist/renderer/entries/workbench-settings/index.html +3 -3
- package/dist/shared/ipc-channels.d.ts +3 -2
- package/dist/shared/ipc-channels.js +4 -3
- package/dist/shared/ipc-schemas.d.ts +2 -0
- package/dist/shared/ipc-schemas.js +2 -0
- package/dist/shared/types.d.ts +55 -3
- package/dist/simulator/assets/simulator-CILbo0Ji.js +9 -0
- package/dist/simulator/simulator.html +1 -1
- package/package.json +3 -35
- package/dist/main/simulator-apis.d.ts +0 -23
- package/dist/main/simulator-apis.js +0 -24
- package/dist/renderer/assets/index-D8VFYBh-.js +0 -46
- package/dist/simulator/assets/simulator-CZc88Jeh.js +0 -9
|
@@ -124,6 +124,13 @@ function toDisposable(fn) {
|
|
|
124
124
|
var DisposableRegistry = class {
|
|
125
125
|
entries = [];
|
|
126
126
|
_disposed = false;
|
|
127
|
+
/**
|
|
128
|
+
* Number of live entries. A wrapper's `dispose` splices its entry out and
|
|
129
|
+
* `disposeAll` clears the array, so `entries.length` is the live count.
|
|
130
|
+
*/
|
|
131
|
+
get size() {
|
|
132
|
+
return this.entries.length;
|
|
133
|
+
}
|
|
127
134
|
add(d) {
|
|
128
135
|
if (this._disposed) {
|
|
129
136
|
throw new Error("cannot add to disposed registry");
|
|
@@ -391,6 +398,7 @@ function createWorkbenchSenderPolicy(ctx) {
|
|
|
391
398
|
if (sender.isDestroyed()) return false;
|
|
392
399
|
if (ctx.windows.isMainSender(sender.id)) return true;
|
|
393
400
|
if (ctx.windows.isSettingsWindowSender(sender.id)) return true;
|
|
401
|
+
if (ctx.trustedWindowSenderIds.has(sender.id)) return true;
|
|
394
402
|
const settingsViewId = ctx.views.getSettingsWebContentsId();
|
|
395
403
|
if (settingsViewId != null && sender.id === settingsViewId) return true;
|
|
396
404
|
const popoverViewId = ctx.views.getPopoverWebContentsId();
|
|
@@ -490,15 +498,16 @@ var PopoverChannel = {
|
|
|
490
498
|
var ToolbarChannel = {
|
|
491
499
|
GetActions: "toolbar:getActions",
|
|
492
500
|
ActionsChanged: "toolbar:actionsChanged",
|
|
493
|
-
/**
|
|
494
|
-
|
|
501
|
+
/** Invoke a toolbar action by id: `invoke(Invoke, actionId)`. */
|
|
502
|
+
Invoke: "toolbar:invoke"
|
|
495
503
|
};
|
|
496
504
|
var WindowChannel = {
|
|
497
505
|
NavigateBack: "window:navigateBack"
|
|
498
506
|
};
|
|
499
507
|
var AppChannel = {
|
|
500
508
|
GetPreloadPath: "app:getPreloadPath",
|
|
501
|
-
GetBranding: "app:getBranding"
|
|
509
|
+
GetBranding: "app:getBranding",
|
|
510
|
+
GetHeaderHeight: "app:getHeaderHeight"
|
|
502
511
|
};
|
|
503
512
|
var AutomationChannel = {
|
|
504
513
|
GetPort: "automation:port"
|
|
@@ -578,43 +587,43 @@ import { WebContentsView as WebContentsView2, webContents } from "electron";
|
|
|
578
587
|
import path6 from "path";
|
|
579
588
|
|
|
580
589
|
// src/main/services/layout/index.ts
|
|
581
|
-
var HEADER_H = 40;
|
|
582
590
|
var SPLITTER_W = 4;
|
|
583
591
|
function getRightX(simWidth) {
|
|
584
592
|
return simWidth + SPLITTER_W;
|
|
585
593
|
}
|
|
586
|
-
function computeRightPanelBounds(contentWidth, contentHeight, simWidth) {
|
|
594
|
+
function computeRightPanelBounds(contentWidth, contentHeight, simWidth, headerHeight) {
|
|
587
595
|
const x = getRightX(simWidth);
|
|
588
596
|
return {
|
|
589
597
|
x,
|
|
590
|
-
y:
|
|
598
|
+
y: headerHeight,
|
|
591
599
|
width: Math.max(1, contentWidth - x),
|
|
592
|
-
height: Math.max(1, contentHeight -
|
|
600
|
+
height: Math.max(1, contentHeight - headerHeight)
|
|
593
601
|
};
|
|
594
602
|
}
|
|
595
|
-
function computeSimulatorBounds(contentWidth, contentHeight, simWidth) {
|
|
596
|
-
return computeRightPanelBounds(contentWidth, contentHeight, simWidth);
|
|
603
|
+
function computeSimulatorBounds(contentWidth, contentHeight, simWidth, headerHeight) {
|
|
604
|
+
return computeRightPanelBounds(contentWidth, contentHeight, simWidth, headerHeight);
|
|
597
605
|
}
|
|
598
606
|
var SETTINGS_W = 320;
|
|
599
|
-
function computeSettingsBounds(contentWidth, contentHeight) {
|
|
607
|
+
function computeSettingsBounds(contentWidth, contentHeight, headerHeight) {
|
|
600
608
|
return {
|
|
601
609
|
x: Math.max(0, contentWidth - SETTINGS_W),
|
|
602
|
-
y:
|
|
610
|
+
y: headerHeight,
|
|
603
611
|
width: SETTINGS_W,
|
|
604
|
-
height: Math.max(1, contentHeight -
|
|
612
|
+
height: Math.max(1, contentHeight - headerHeight)
|
|
605
613
|
};
|
|
606
614
|
}
|
|
607
|
-
function computePopoverBounds(contentWidth, contentHeight) {
|
|
615
|
+
function computePopoverBounds(contentWidth, contentHeight, headerHeight) {
|
|
608
616
|
return {
|
|
609
617
|
x: 0,
|
|
610
|
-
y:
|
|
618
|
+
y: headerHeight,
|
|
611
619
|
width: contentWidth,
|
|
612
|
-
height: contentHeight -
|
|
620
|
+
height: contentHeight - headerHeight
|
|
613
621
|
};
|
|
614
622
|
}
|
|
615
623
|
|
|
616
624
|
// src/main/services/views/view-manager.ts
|
|
617
625
|
function createViewManager(ctx) {
|
|
626
|
+
const headerHeight = ctx.headerHeight ?? 40;
|
|
618
627
|
let simulatorView = null;
|
|
619
628
|
let simulatorViewAdded = false;
|
|
620
629
|
let settingsView = null;
|
|
@@ -640,17 +649,17 @@ function createViewManager(ctx) {
|
|
|
640
649
|
function applySimulatorBounds(simWidth) {
|
|
641
650
|
if (!simulatorView || ctx.windows.mainWindow.isDestroyed()) return;
|
|
642
651
|
const [w = 0, h = 0] = ctx.windows.mainWindow.getContentSize();
|
|
643
|
-
simulatorView.setBounds(computeSimulatorBounds(w, h, simWidth));
|
|
652
|
+
simulatorView.setBounds(computeSimulatorBounds(w, h, simWidth, headerHeight));
|
|
644
653
|
}
|
|
645
654
|
function applySettingsBounds() {
|
|
646
655
|
if (!settingsView || ctx.windows.mainWindow.isDestroyed()) return;
|
|
647
656
|
const [w = 0, h = 0] = ctx.windows.mainWindow.getContentSize();
|
|
648
|
-
settingsView.setBounds(computeSettingsBounds(w, h));
|
|
657
|
+
settingsView.setBounds(computeSettingsBounds(w, h, headerHeight));
|
|
649
658
|
}
|
|
650
659
|
function applyPopoverBounds() {
|
|
651
660
|
if (!popoverView || ctx.windows.mainWindow.isDestroyed()) return;
|
|
652
661
|
const [w = 0, h = 0] = ctx.windows.mainWindow.getContentSize();
|
|
653
|
-
popoverView.setBounds(computePopoverBounds(w, h));
|
|
662
|
+
popoverView.setBounds(computePopoverBounds(w, h, headerHeight));
|
|
654
663
|
}
|
|
655
664
|
function attachSimulator(simWcId, simWidth) {
|
|
656
665
|
const sim = webContents.fromId(simWcId);
|
|
@@ -1248,6 +1257,53 @@ function createLocalProjectsProvider() {
|
|
|
1248
1257
|
};
|
|
1249
1258
|
}
|
|
1250
1259
|
|
|
1260
|
+
// src/main/services/simulator/custom-apis.ts
|
|
1261
|
+
function createSimulatorApiRegistry() {
|
|
1262
|
+
const handlers2 = /* @__PURE__ */ new Map();
|
|
1263
|
+
return {
|
|
1264
|
+
register(name, handler) {
|
|
1265
|
+
handlers2.set(name, handler);
|
|
1266
|
+
return () => {
|
|
1267
|
+
if (handlers2.get(name) === handler) handlers2.delete(name);
|
|
1268
|
+
};
|
|
1269
|
+
},
|
|
1270
|
+
list() {
|
|
1271
|
+
return Array.from(handlers2.keys());
|
|
1272
|
+
},
|
|
1273
|
+
async invoke(name, params) {
|
|
1274
|
+
const handler = handlers2.get(name);
|
|
1275
|
+
if (!handler) throw new Error(`Simulator API "${name}" is not registered`);
|
|
1276
|
+
return await handler(params);
|
|
1277
|
+
},
|
|
1278
|
+
clear() {
|
|
1279
|
+
handlers2.clear();
|
|
1280
|
+
}
|
|
1281
|
+
};
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
// src/main/services/toolbar/toolbar-store.ts
|
|
1285
|
+
function createToolbarStore() {
|
|
1286
|
+
let actions = [];
|
|
1287
|
+
return {
|
|
1288
|
+
set(next) {
|
|
1289
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1290
|
+
for (const action of next) {
|
|
1291
|
+
if (seen.has(action.id)) {
|
|
1292
|
+
throw new Error(`Duplicate toolbar action id "${action.id}"`);
|
|
1293
|
+
}
|
|
1294
|
+
seen.add(action.id);
|
|
1295
|
+
}
|
|
1296
|
+
actions = next.slice();
|
|
1297
|
+
},
|
|
1298
|
+
list() {
|
|
1299
|
+
return actions.map(({ id, label }) => ({ id, label }));
|
|
1300
|
+
},
|
|
1301
|
+
getHandler(id) {
|
|
1302
|
+
return actions.find((a) => a.id === id)?.handler;
|
|
1303
|
+
}
|
|
1304
|
+
};
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1251
1307
|
// src/main/services/projects/templates.ts
|
|
1252
1308
|
function resolveTemplates(builtin, injected, mode) {
|
|
1253
1309
|
let kept;
|
|
@@ -1309,10 +1365,13 @@ function createWorkbenchContext(opts) {
|
|
|
1309
1365
|
panels: opts.panels ?? ["wxml", "console", "appdata", "storage"],
|
|
1310
1366
|
apiNamespaces: opts.apiNamespaces ?? [],
|
|
1311
1367
|
appName: opts.appName ?? "Dimina DevTools",
|
|
1312
|
-
|
|
1368
|
+
headerHeight: opts.headerHeight ?? 40,
|
|
1313
1369
|
brandingProvider: opts.brandingProvider
|
|
1314
1370
|
};
|
|
1315
1371
|
ctx.registry = new DisposableRegistry();
|
|
1372
|
+
ctx.trustedWindowSenderIds = /* @__PURE__ */ new Map();
|
|
1373
|
+
ctx.simulatorApis = createSimulatorApiRegistry();
|
|
1374
|
+
ctx.toolbar = createToolbarStore();
|
|
1316
1375
|
ctx.windows = createWindowService(opts.mainWindow);
|
|
1317
1376
|
ctx.views = createViewManager(ctx);
|
|
1318
1377
|
ctx.notify = createRendererNotifier(ctx);
|
|
@@ -1461,7 +1520,7 @@ var IpcRegistry = class {
|
|
|
1461
1520
|
registry = new DisposableRegistry();
|
|
1462
1521
|
handle(channel, fn) {
|
|
1463
1522
|
const policy = this.policy;
|
|
1464
|
-
const guarded = policy ? (event, ...args) => {
|
|
1523
|
+
const guarded = policy ? async (event, ...args) => {
|
|
1465
1524
|
const sender = event.sender;
|
|
1466
1525
|
if (!policy(sender)) {
|
|
1467
1526
|
console.warn(
|
|
@@ -1516,6 +1575,8 @@ function registerAppIpc(ctx) {
|
|
|
1516
1575
|
}).handle(AppChannel.GetBranding, async () => {
|
|
1517
1576
|
if (ctx.brandingProvider) return ctx.brandingProvider();
|
|
1518
1577
|
return { appName: ctx.appName };
|
|
1578
|
+
}).handle(AppChannel.GetHeaderHeight, () => {
|
|
1579
|
+
return ctx.headerHeight;
|
|
1519
1580
|
});
|
|
1520
1581
|
}
|
|
1521
1582
|
|
|
@@ -1549,6 +1610,7 @@ var SimulatorCustomApiInvokeSchema = z.tuple([
|
|
|
1549
1610
|
z.string().min(1).max(256),
|
|
1550
1611
|
z.unknown()
|
|
1551
1612
|
]);
|
|
1613
|
+
var ToolbarInvokeSchema = z.tuple([z.string().min(1).max(256)]);
|
|
1552
1614
|
var ProjectGetPagesSchema = z.tuple([AbsolutePath]);
|
|
1553
1615
|
var ProjectGetCompileConfigSchema = z.tuple([AbsolutePath]);
|
|
1554
1616
|
var ProjectsRemoveSchema = z.tuple([AbsolutePath]);
|
|
@@ -1585,31 +1647,6 @@ var PanelSelectSchema = z.tuple([z.string().min(1).max(200)]);
|
|
|
1585
1647
|
var ProjectCaptureThumbnailSchema = z.tuple([AbsolutePath]);
|
|
1586
1648
|
var ProjectGetThumbnailSchema = z.tuple([AbsolutePath]);
|
|
1587
1649
|
|
|
1588
|
-
// src/main/services/simulator/custom-apis.ts
|
|
1589
|
-
function createSimulatorApiRegistry() {
|
|
1590
|
-
const handlers2 = /* @__PURE__ */ new Map();
|
|
1591
|
-
return {
|
|
1592
|
-
register(name, handler) {
|
|
1593
|
-
handlers2.set(name, handler);
|
|
1594
|
-
return () => {
|
|
1595
|
-
if (handlers2.get(name) === handler) handlers2.delete(name);
|
|
1596
|
-
};
|
|
1597
|
-
},
|
|
1598
|
-
list() {
|
|
1599
|
-
return Array.from(handlers2.keys());
|
|
1600
|
-
},
|
|
1601
|
-
async invoke(name, params) {
|
|
1602
|
-
const handler = handlers2.get(name);
|
|
1603
|
-
if (!handler) throw new Error(`Simulator API "${name}" is not registered`);
|
|
1604
|
-
return await handler(params);
|
|
1605
|
-
},
|
|
1606
|
-
clear() {
|
|
1607
|
-
handlers2.clear();
|
|
1608
|
-
}
|
|
1609
|
-
};
|
|
1610
|
-
}
|
|
1611
|
-
var simulatorApiRegistry = createSimulatorApiRegistry();
|
|
1612
|
-
|
|
1613
1650
|
// src/main/ipc/simulator.ts
|
|
1614
1651
|
function registerSimulatorIpc(ctx) {
|
|
1615
1652
|
return new IpcRegistry(ctx.senderPolicy).handle(SimulatorChannel.Attach, (_, ...args) => {
|
|
@@ -1624,10 +1661,10 @@ function registerSimulatorIpc(ctx) {
|
|
|
1624
1661
|
const [visible, simWidth] = validate(SimulatorChannel.SetVisible, SimulatorSetVisibleSchema, args);
|
|
1625
1662
|
ctx.views.setVisible(visible, simWidth);
|
|
1626
1663
|
}).handle(SimulatorCustomApiChannel.List, () => {
|
|
1627
|
-
return
|
|
1664
|
+
return ctx.simulatorApis.list();
|
|
1628
1665
|
}).handle(SimulatorCustomApiChannel.Invoke, (_, ...args) => {
|
|
1629
1666
|
const [name, params] = validate(SimulatorCustomApiChannel.Invoke, SimulatorCustomApiInvokeSchema, args);
|
|
1630
|
-
return
|
|
1667
|
+
return ctx.simulatorApis.invoke(name, params);
|
|
1631
1668
|
});
|
|
1632
1669
|
}
|
|
1633
1670
|
|
|
@@ -2000,9 +2037,15 @@ var settingsModule = {
|
|
|
2000
2037
|
|
|
2001
2038
|
// src/main/ipc/toolbar.ts
|
|
2002
2039
|
function registerToolbarIpc(ctx) {
|
|
2003
|
-
return new IpcRegistry(ctx.senderPolicy).handle(ToolbarChannel.GetActions,
|
|
2004
|
-
|
|
2005
|
-
|
|
2040
|
+
return new IpcRegistry(ctx.senderPolicy).handle(ToolbarChannel.GetActions, () => {
|
|
2041
|
+
return ctx.toolbar.list();
|
|
2042
|
+
}).handle(ToolbarChannel.Invoke, async (_, ...args) => {
|
|
2043
|
+
const [id] = validate(ToolbarChannel.Invoke, ToolbarInvokeSchema, args);
|
|
2044
|
+
const handler = ctx.toolbar.getHandler(id);
|
|
2045
|
+
if (!handler) {
|
|
2046
|
+
throw new Error(`Toolbar action "${id}" is not registered`);
|
|
2047
|
+
}
|
|
2048
|
+
await handler();
|
|
2006
2049
|
});
|
|
2007
2050
|
}
|
|
2008
2051
|
|
|
@@ -3594,6 +3637,27 @@ var BUILTIN_MODULES = {
|
|
|
3594
3637
|
popover: popoverModule,
|
|
3595
3638
|
settings: settingsModule
|
|
3596
3639
|
};
|
|
3640
|
+
function registerTrustedWindow(context, win) {
|
|
3641
|
+
const senderId = win.webContents.id;
|
|
3642
|
+
const counts = context.trustedWindowSenderIds;
|
|
3643
|
+
counts.set(senderId, (counts.get(senderId) ?? 0) + 1);
|
|
3644
|
+
let removed = false;
|
|
3645
|
+
const onClosed = () => {
|
|
3646
|
+
counts.delete(senderId);
|
|
3647
|
+
win.removeListener("closed", onClosed);
|
|
3648
|
+
};
|
|
3649
|
+
function remove() {
|
|
3650
|
+
if (removed) return;
|
|
3651
|
+
removed = true;
|
|
3652
|
+
win.removeListener("closed", onClosed);
|
|
3653
|
+
const count = counts.get(senderId);
|
|
3654
|
+
if (count === void 0) return;
|
|
3655
|
+
if (count <= 1) counts.delete(senderId);
|
|
3656
|
+
else counts.set(senderId, count - 1);
|
|
3657
|
+
}
|
|
3658
|
+
win.once("closed", onClosed);
|
|
3659
|
+
return toDisposable(remove);
|
|
3660
|
+
}
|
|
3597
3661
|
function parseAutoArgs() {
|
|
3598
3662
|
const argv = process.argv;
|
|
3599
3663
|
let auto = false;
|
|
@@ -3652,8 +3716,8 @@ function createContext(config, mainWindow, rendererDir2) {
|
|
|
3652
3716
|
panels: config.panels,
|
|
3653
3717
|
appName: config.appName,
|
|
3654
3718
|
apiNamespaces: config.apiNamespaces,
|
|
3719
|
+
headerHeight: config.headerHeight,
|
|
3655
3720
|
brandingProvider: config.brandingProvider,
|
|
3656
|
-
toolbarActions: config.toolbarActions,
|
|
3657
3721
|
// The host-supplied ProjectsProvider / template types in `shared/types`
|
|
3658
3722
|
// are structurally compatible with the main-process equivalents —
|
|
3659
3723
|
// these casts are safe; we re-narrow at the workspace-service /
|
|
@@ -3670,9 +3734,18 @@ function registerBuiltinModules(config, context) {
|
|
|
3670
3734
|
if (modules[moduleId]) context.registry.add(BUILTIN_MODULES[moduleId].setup(context));
|
|
3671
3735
|
});
|
|
3672
3736
|
}
|
|
3737
|
+
function toMenuContext(context) {
|
|
3738
|
+
const menuContext = { ...context };
|
|
3739
|
+
delete menuContext.registry;
|
|
3740
|
+
delete menuContext.senderPolicy;
|
|
3741
|
+
delete menuContext.trustedWindowSenderIds;
|
|
3742
|
+
delete menuContext.simulatorApis;
|
|
3743
|
+
delete menuContext.toolbar;
|
|
3744
|
+
return menuContext;
|
|
3745
|
+
}
|
|
3673
3746
|
function installMenu(config, mainWindow, context) {
|
|
3674
3747
|
if (config.menuBuilder) {
|
|
3675
|
-
config.menuBuilder(mainWindow, context);
|
|
3748
|
+
config.menuBuilder(mainWindow, toMenuContext(context));
|
|
3676
3749
|
} else {
|
|
3677
3750
|
installAppMenu(context);
|
|
3678
3751
|
}
|
|
@@ -3746,9 +3819,23 @@ function createWorkbenchApp(config = {}) {
|
|
|
3746
3819
|
context.registry.add(installThemeBackgroundSync());
|
|
3747
3820
|
registerBuiltinModules(config, context);
|
|
3748
3821
|
installMenu(config, mainWindow, context);
|
|
3822
|
+
const hostIpc = new IpcRegistry(context.senderPolicy);
|
|
3823
|
+
context.registry.add(hostIpc);
|
|
3749
3824
|
const instance = {
|
|
3750
3825
|
mainWindow,
|
|
3751
3826
|
context,
|
|
3827
|
+
ipc: hostIpc,
|
|
3828
|
+
// Return the registry wrapper, not the raw disposable: disposing the
|
|
3829
|
+
// wrapper splices the registry entry out AND drives the underlying
|
|
3830
|
+
// teardown, so a single dispose leaves no dead entry behind.
|
|
3831
|
+
registerTrustedWindow: (win) => context.registry.add(registerTrustedWindow(context, win)),
|
|
3832
|
+
registerSimulatorApi: (name, handler) => context.registry.add(toDisposable(context.simulatorApis.register(name, handler))),
|
|
3833
|
+
toolbar: {
|
|
3834
|
+
set: (actions) => {
|
|
3835
|
+
context.toolbar.set(actions);
|
|
3836
|
+
context.notify.toolbarActionsChanged();
|
|
3837
|
+
}
|
|
3838
|
+
},
|
|
3752
3839
|
dispose: () => disposeContext(context)
|
|
3753
3840
|
};
|
|
3754
3841
|
if (config.onSetup) {
|
|
@@ -3758,6 +3845,7 @@ function createWorkbenchApp(config = {}) {
|
|
|
3758
3845
|
instance.updateManager = new UpdateManager({
|
|
3759
3846
|
checker: config.updateChecker,
|
|
3760
3847
|
mainWindow,
|
|
3848
|
+
senderPolicy: context.senderPolicy,
|
|
3761
3849
|
checkInterval: config.updateOptions?.checkInterval,
|
|
3762
3850
|
initialDelay: config.updateOptions?.initialDelay,
|
|
3763
3851
|
getCurrentVersion: config.updateOptions?.getCurrentVersion
|
package/dist/main/ipc/app.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { WorkbenchContext } from '../services/workbench-context.js';
|
|
2
2
|
import type { Disposable } from '../utils/disposable.js';
|
|
3
|
-
export declare function registerAppIpc(ctx: Pick<WorkbenchContext, 'preloadPath' | 'brandingProvider' | 'appName' | 'senderPolicy'>): Disposable;
|
|
3
|
+
export declare function registerAppIpc(ctx: Pick<WorkbenchContext, 'preloadPath' | 'brandingProvider' | 'appName' | 'headerHeight' | 'senderPolicy'>): Disposable;
|
|
4
4
|
//# sourceMappingURL=app.d.ts.map
|
package/dist/main/ipc/app.js
CHANGED
|
@@ -10,6 +10,9 @@ export function registerAppIpc(ctx) {
|
|
|
10
10
|
if (ctx.brandingProvider)
|
|
11
11
|
return ctx.brandingProvider();
|
|
12
12
|
return { appName: ctx.appName };
|
|
13
|
+
})
|
|
14
|
+
.handle(AppChannel.GetHeaderHeight, () => {
|
|
15
|
+
return ctx.headerHeight;
|
|
13
16
|
});
|
|
14
17
|
}
|
|
15
18
|
//# sourceMappingURL=app.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { WorkbenchContext } from '../services/workbench-context.js';
|
|
2
2
|
import type { Disposable } from '../utils/disposable.js';
|
|
3
|
-
export declare function registerSimulatorIpc(ctx: Pick<WorkbenchContext, 'views' | 'notify' | 'senderPolicy'>): Disposable;
|
|
3
|
+
export declare function registerSimulatorIpc(ctx: Pick<WorkbenchContext, 'views' | 'notify' | 'senderPolicy' | 'simulatorApis'>): Disposable;
|
|
4
4
|
//# sourceMappingURL=simulator.d.ts.map
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { SimulatorChannel, SimulatorCustomApiChannel } from '../../shared/ipc-channels.js';
|
|
2
2
|
import { SimulatorAttachSchema, SimulatorCustomApiInvokeSchema, SimulatorResizeSchema, SimulatorSetVisibleSchema, } from '../../shared/ipc-schemas.js';
|
|
3
|
-
import { simulatorApiRegistry } from '../services/simulator/custom-apis.js';
|
|
4
3
|
import { validate } from '../utils/ipc-schema.js';
|
|
5
4
|
import { IpcRegistry } from '../utils/ipc-registry.js';
|
|
6
5
|
export function registerSimulatorIpc(ctx) {
|
|
@@ -21,11 +20,11 @@ export function registerSimulatorIpc(ctx) {
|
|
|
21
20
|
ctx.views.setVisible(visible, simWidth);
|
|
22
21
|
})
|
|
23
22
|
.handle(SimulatorCustomApiChannel.List, () => {
|
|
24
|
-
return
|
|
23
|
+
return ctx.simulatorApis.list();
|
|
25
24
|
})
|
|
26
25
|
.handle(SimulatorCustomApiChannel.Invoke, (_, ...args) => {
|
|
27
26
|
const [name, params] = validate(SimulatorCustomApiChannel.Invoke, SimulatorCustomApiInvokeSchema, args);
|
|
28
|
-
return
|
|
27
|
+
return ctx.simulatorApis.invoke(name, params);
|
|
29
28
|
});
|
|
30
29
|
}
|
|
31
30
|
//# sourceMappingURL=simulator.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { WorkbenchContext } from '../services/workbench-context.js';
|
|
2
2
|
import type { Disposable } from '../utils/disposable.js';
|
|
3
|
-
export declare function registerToolbarIpc(ctx: Pick<WorkbenchContext, '
|
|
3
|
+
export declare function registerToolbarIpc(ctx: Pick<WorkbenchContext, 'toolbar' | 'senderPolicy'>): Disposable;
|
|
4
4
|
//# sourceMappingURL=toolbar.d.ts.map
|
package/dist/main/ipc/toolbar.js
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import { ToolbarChannel } from '../../shared/ipc-channels.js';
|
|
2
|
+
import { ToolbarInvokeSchema } from '../../shared/ipc-schemas.js';
|
|
3
|
+
import { validate } from '../utils/ipc-schema.js';
|
|
2
4
|
import { IpcRegistry } from '../utils/ipc-registry.js';
|
|
3
5
|
export function registerToolbarIpc(ctx) {
|
|
4
6
|
return new IpcRegistry(ctx.senderPolicy)
|
|
5
|
-
.handle(ToolbarChannel.GetActions,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
return
|
|
7
|
+
.handle(ToolbarChannel.GetActions, () => {
|
|
8
|
+
// Project to {id,label}[] — the non-serialisable handler never leaves
|
|
9
|
+
// the main process.
|
|
10
|
+
return ctx.toolbar.list();
|
|
11
|
+
})
|
|
12
|
+
.handle(ToolbarChannel.Invoke, async (_, ...args) => {
|
|
13
|
+
const [id] = validate(ToolbarChannel.Invoke, ToolbarInvokeSchema, args);
|
|
14
|
+
const handler = ctx.toolbar.getHandler(id);
|
|
15
|
+
if (!handler) {
|
|
16
|
+
throw new Error(`Toolbar action "${id}" is not registered`);
|
|
17
|
+
}
|
|
18
|
+
await handler();
|
|
9
19
|
});
|
|
10
20
|
}
|
|
11
21
|
//# sourceMappingURL=toolbar.js.map
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
/** Layout constants (px) */
|
|
2
|
-
export declare let HEADER_H: number;
|
|
3
2
|
export declare const SPLITTER_W = 4;
|
|
4
|
-
/**
|
|
5
|
-
* Override the header height used for layout calculations.
|
|
6
|
-
* Call this before any views are positioned (e.g. in onSetup).
|
|
7
|
-
*/
|
|
8
|
-
export declare function setHeaderHeight(h: number): void;
|
|
9
3
|
/**
|
|
10
4
|
* X coordinate where the right panel starts (simulator width + splitter).
|
|
11
5
|
*/
|
|
@@ -16,12 +10,12 @@ export interface Bounds {
|
|
|
16
10
|
width: number;
|
|
17
11
|
height: number;
|
|
18
12
|
}
|
|
19
|
-
export declare function computeRightPanelBounds(contentWidth: number, contentHeight: number, simWidth: number): Bounds;
|
|
13
|
+
export declare function computeRightPanelBounds(contentWidth: number, contentHeight: number, simWidth: number, headerHeight: number): Bounds;
|
|
20
14
|
/**
|
|
21
15
|
* Compute bounds for DevTools view (same as right panel, overlays it).
|
|
22
16
|
*/
|
|
23
|
-
export declare function computeSimulatorBounds(contentWidth: number, contentHeight: number, simWidth: number): Bounds;
|
|
17
|
+
export declare function computeSimulatorBounds(contentWidth: number, contentHeight: number, simWidth: number, headerHeight: number): Bounds;
|
|
24
18
|
export declare const SETTINGS_W = 320;
|
|
25
|
-
export declare function computeSettingsBounds(contentWidth: number, contentHeight: number): Bounds;
|
|
26
|
-
export declare function computePopoverBounds(contentWidth: number, contentHeight: number): Bounds;
|
|
19
|
+
export declare function computeSettingsBounds(contentWidth: number, contentHeight: number, headerHeight: number): Bounds;
|
|
20
|
+
export declare function computePopoverBounds(contentWidth: number, contentHeight: number, headerHeight: number): Bounds;
|
|
27
21
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,49 +1,41 @@
|
|
|
1
1
|
/** Layout constants (px) */
|
|
2
|
-
export let HEADER_H = 40;
|
|
3
2
|
export const SPLITTER_W = 4;
|
|
4
|
-
/**
|
|
5
|
-
* Override the header height used for layout calculations.
|
|
6
|
-
* Call this before any views are positioned (e.g. in onSetup).
|
|
7
|
-
*/
|
|
8
|
-
export function setHeaderHeight(h) {
|
|
9
|
-
HEADER_H = h;
|
|
10
|
-
}
|
|
11
3
|
/**
|
|
12
4
|
* X coordinate where the right panel starts (simulator width + splitter).
|
|
13
5
|
*/
|
|
14
6
|
export function getRightX(simWidth) {
|
|
15
7
|
return simWidth + SPLITTER_W;
|
|
16
8
|
}
|
|
17
|
-
export function computeRightPanelBounds(contentWidth, contentHeight, simWidth) {
|
|
9
|
+
export function computeRightPanelBounds(contentWidth, contentHeight, simWidth, headerHeight) {
|
|
18
10
|
const x = getRightX(simWidth);
|
|
19
11
|
return {
|
|
20
12
|
x,
|
|
21
|
-
y:
|
|
13
|
+
y: headerHeight,
|
|
22
14
|
width: Math.max(1, contentWidth - x),
|
|
23
|
-
height: Math.max(1, contentHeight -
|
|
15
|
+
height: Math.max(1, contentHeight - headerHeight),
|
|
24
16
|
};
|
|
25
17
|
}
|
|
26
18
|
/**
|
|
27
19
|
* Compute bounds for DevTools view (same as right panel, overlays it).
|
|
28
20
|
*/
|
|
29
|
-
export function computeSimulatorBounds(contentWidth, contentHeight, simWidth) {
|
|
30
|
-
return computeRightPanelBounds(contentWidth, contentHeight, simWidth);
|
|
21
|
+
export function computeSimulatorBounds(contentWidth, contentHeight, simWidth, headerHeight) {
|
|
22
|
+
return computeRightPanelBounds(contentWidth, contentHeight, simWidth, headerHeight);
|
|
31
23
|
}
|
|
32
24
|
export const SETTINGS_W = 320;
|
|
33
|
-
export function computeSettingsBounds(contentWidth, contentHeight) {
|
|
25
|
+
export function computeSettingsBounds(contentWidth, contentHeight, headerHeight) {
|
|
34
26
|
return {
|
|
35
27
|
x: Math.max(0, contentWidth - SETTINGS_W),
|
|
36
|
-
y:
|
|
28
|
+
y: headerHeight,
|
|
37
29
|
width: SETTINGS_W,
|
|
38
|
-
height: Math.max(1, contentHeight -
|
|
30
|
+
height: Math.max(1, contentHeight - headerHeight),
|
|
39
31
|
};
|
|
40
32
|
}
|
|
41
|
-
export function computePopoverBounds(contentWidth, contentHeight) {
|
|
33
|
+
export function computePopoverBounds(contentWidth, contentHeight, headerHeight) {
|
|
42
34
|
return {
|
|
43
35
|
x: 0,
|
|
44
|
-
y:
|
|
36
|
+
y: headerHeight,
|
|
45
37
|
width: contentWidth,
|
|
46
|
-
height: contentHeight -
|
|
38
|
+
height: contentHeight - headerHeight,
|
|
47
39
|
};
|
|
48
40
|
}
|
|
49
41
|
//# sourceMappingURL=index.js.map
|
|
@@ -4,8 +4,7 @@ import type { WorkbenchContext } from './workbench-context.js';
|
|
|
4
4
|
* A composable unit of workbench functionality.
|
|
5
5
|
*
|
|
6
6
|
* Built-in modules (projects, session, simulator, popover, settings) are
|
|
7
|
-
* implemented as `WorkbenchModule` values
|
|
8
|
-
* modules via `WorkbenchAppConfig.extraModules`.
|
|
7
|
+
* implemented as `WorkbenchModule` values.
|
|
9
8
|
*
|
|
10
9
|
* `setup` is invoked once during workbench bootstrap. The returned
|
|
11
10
|
* Disposable is added to `ctx.registry` so module teardown is symmetric
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ToolbarAction, ToolbarActionInput } from '../../../shared/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Per-context store for host-registered toolbar actions.
|
|
4
|
+
*
|
|
5
|
+
* The toolbar is modelled as "one table the host recomputes from its current
|
|
6
|
+
* state": `set()` replaces the whole table atomically. The non-serialisable
|
|
7
|
+
* `handler` is kept main-process side; `list()` projects to `{id,label}[]`
|
|
8
|
+
* for the IPC boundary, and `getHandler()` resolves a handler by id.
|
|
9
|
+
*/
|
|
10
|
+
export interface ToolbarStore {
|
|
11
|
+
/**
|
|
12
|
+
* Atomically replace the whole toolbar table. Validates that every `id` is
|
|
13
|
+
* unique up-front; on a duplicate it throws WITHOUT mutating the store, so
|
|
14
|
+
* a rejected batch leaves the previous table intact.
|
|
15
|
+
*/
|
|
16
|
+
set(actions: ToolbarActionInput[]): void;
|
|
17
|
+
/** Project the current table to `{id,label}[]` — no `handler` leaks out. */
|
|
18
|
+
list(): ToolbarAction[];
|
|
19
|
+
/** Resolve the handler stored under `id`, or `undefined` if unknown. */
|
|
20
|
+
getHandler(id: string): (() => void | Promise<void>) | undefined;
|
|
21
|
+
}
|
|
22
|
+
export declare function createToolbarStore(): ToolbarStore;
|
|
23
|
+
//# sourceMappingURL=toolbar-store.d.ts.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function createToolbarStore() {
|
|
2
|
+
let actions = [];
|
|
3
|
+
return {
|
|
4
|
+
set(next) {
|
|
5
|
+
const seen = new Set();
|
|
6
|
+
for (const action of next) {
|
|
7
|
+
if (seen.has(action.id)) {
|
|
8
|
+
throw new Error(`Duplicate toolbar action id "${action.id}"`);
|
|
9
|
+
}
|
|
10
|
+
seen.add(action.id);
|
|
11
|
+
}
|
|
12
|
+
// Copy so a later host mutation of the passed array can't reach in.
|
|
13
|
+
actions = next.slice();
|
|
14
|
+
},
|
|
15
|
+
list() {
|
|
16
|
+
return actions.map(({ id, label }) => ({ id, label }));
|
|
17
|
+
},
|
|
18
|
+
getHandler(id) {
|
|
19
|
+
return actions.find((a) => a.id === id)?.handler;
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=toolbar-store.js.map
|
|
@@ -9,6 +9,12 @@ export interface ViewManagerContext {
|
|
|
9
9
|
rendererDir: string;
|
|
10
10
|
panels: string[];
|
|
11
11
|
notify: WorkbenchContext['notify'];
|
|
12
|
+
/**
|
|
13
|
+
* Header bar height in px, used to position overlay views below the header.
|
|
14
|
+
* Optional here so partial test contexts compile; `createWorkbenchContext`
|
|
15
|
+
* always supplies it (default 40).
|
|
16
|
+
*/
|
|
17
|
+
headerHeight?: number;
|
|
12
18
|
}
|
|
13
19
|
/**
|
|
14
20
|
* Unified lifecycle manager for Electron WebContentsView overlays.
|
|
@@ -12,6 +12,9 @@ import { getDefaultTab } from '../workbench-context.js';
|
|
|
12
12
|
* on the context object.
|
|
13
13
|
*/
|
|
14
14
|
export function createViewManager(ctx) {
|
|
15
|
+
// Resolve once: full WorkbenchContext always provides headerHeight; partial
|
|
16
|
+
// test contexts may omit it, in which case fall back to the default 40.
|
|
17
|
+
const headerHeight = ctx.headerHeight ?? 40;
|
|
15
18
|
// ── Private mutable state ───────────────────────────────────────────────
|
|
16
19
|
let simulatorView = null;
|
|
17
20
|
let simulatorViewAdded = false;
|
|
@@ -41,19 +44,19 @@ export function createViewManager(ctx) {
|
|
|
41
44
|
if (!simulatorView || ctx.windows.mainWindow.isDestroyed())
|
|
42
45
|
return;
|
|
43
46
|
const [w = 0, h = 0] = ctx.windows.mainWindow.getContentSize();
|
|
44
|
-
simulatorView.setBounds(layout.computeSimulatorBounds(w, h, simWidth));
|
|
47
|
+
simulatorView.setBounds(layout.computeSimulatorBounds(w, h, simWidth, headerHeight));
|
|
45
48
|
}
|
|
46
49
|
function applySettingsBounds() {
|
|
47
50
|
if (!settingsView || ctx.windows.mainWindow.isDestroyed())
|
|
48
51
|
return;
|
|
49
52
|
const [w = 0, h = 0] = ctx.windows.mainWindow.getContentSize();
|
|
50
|
-
settingsView.setBounds(layout.computeSettingsBounds(w, h));
|
|
53
|
+
settingsView.setBounds(layout.computeSettingsBounds(w, h, headerHeight));
|
|
51
54
|
}
|
|
52
55
|
function applyPopoverBounds() {
|
|
53
56
|
if (!popoverView || ctx.windows.mainWindow.isDestroyed())
|
|
54
57
|
return;
|
|
55
58
|
const [w = 0, h = 0] = ctx.windows.mainWindow.getContentSize();
|
|
56
|
-
popoverView.setBounds(layout.computePopoverBounds(w, h));
|
|
59
|
+
popoverView.setBounds(layout.computePopoverBounds(w, h, headerHeight));
|
|
57
60
|
}
|
|
58
61
|
// ── ViewManager methods ─────────────────────────────────────────────────
|
|
59
62
|
function attachSimulator(simWcId, simWidth) {
|