@dimina-kit/devtools 0.3.1-dev.20260518114324 → 0.3.2-dev.20260522085907
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 +33 -71
- package/dist/main/app/app.js +5 -0
- package/dist/main/app/bootstrap.js +2 -1
- package/dist/main/app/launch.d.ts +1 -1
- package/dist/main/app/launch.js +6 -7
- package/dist/main/index.bundle.js +306 -317
- package/dist/main/ipc/panels.js +3 -5
- package/dist/main/ipc/projects.d.ts +1 -1
- package/dist/main/ipc/projects.js +5 -5
- package/dist/main/ipc/settings.d.ts +1 -1
- package/dist/main/ipc/settings.js +14 -1
- package/dist/main/ipc/simulator.d.ts +1 -1
- package/dist/main/ipc/simulator.js +1 -10
- package/dist/main/services/automation/exec.d.ts +2 -0
- package/dist/main/services/automation/exec.js +7 -9
- package/dist/main/services/automation/handlers/app.js +37 -51
- package/dist/main/services/automation/handlers/element.js +27 -41
- package/dist/main/services/default-adapter.js +3 -3
- package/dist/main/services/mcp/index.d.ts +1 -0
- package/dist/main/services/mcp/index.js +1 -0
- package/dist/main/services/mcp/server.js +5 -0
- package/dist/main/services/mcp/status.d.ts +10 -0
- package/dist/main/services/mcp/status.js +14 -0
- package/dist/main/services/mcp/target-manager.js +2 -1
- package/dist/main/services/notifications/renderer-notifier.d.ts +3 -3
- package/dist/main/services/notifications/renderer-notifier.js +3 -6
- package/dist/main/services/projects/local-provider.js +3 -3
- package/dist/main/services/projects/project-repository.d.ts +0 -1
- package/dist/main/services/settings/index.js +2 -1
- package/dist/main/services/simulator-storage/index.js +47 -77
- package/dist/main/services/views/view-manager.d.ts +3 -7
- package/dist/main/services/views/view-manager.js +20 -27
- package/dist/main/services/window-service.d.ts +3 -3
- package/dist/main/services/workbench-context.d.ts +3 -6
- package/dist/main/services/workbench-context.js +1 -3
- package/dist/main/services/workspace/workspace-service.js +8 -24
- package/dist/main/utils/theme.d.ts +24 -0
- package/dist/main/utils/theme.js +38 -1
- package/dist/preload/index.d.ts +5 -2
- package/dist/preload/index.js +3 -2
- package/dist/preload/instrumentation/app-data.d.ts +32 -2
- package/dist/preload/instrumentation/app-data.js +187 -172
- package/dist/preload/instrumentation/index.d.ts +2 -2
- package/dist/preload/instrumentation/index.js +2 -2
- package/dist/preload/instrumentation/wxml.d.ts +16 -4
- package/dist/preload/instrumentation/wxml.js +188 -178
- package/dist/preload/miniapp-snapshot/host.d.ts +12 -0
- package/dist/preload/miniapp-snapshot/host.js +117 -0
- package/dist/preload/miniapp-snapshot/types.d.ts +62 -0
- package/dist/preload/miniapp-snapshot/types.js +15 -0
- package/dist/preload/runtime/bridge.js +5 -24
- package/dist/preload/runtime/custom-apis.d.ts +1 -1
- package/dist/preload/runtime/custom-apis.js +3 -7
- package/dist/preload/shared/expose.d.ts +15 -0
- package/dist/preload/shared/expose.js +33 -0
- package/dist/preload/shared/page-iframe.d.ts +3 -0
- package/dist/preload/shared/page-iframe.js +6 -0
- package/dist/preload/shared/types.d.ts +2 -0
- package/dist/preload/windows/simulator.js +400 -348
- package/dist/renderer/assets/constants-DI382mTP.js +2 -0
- package/dist/renderer/assets/index-D8VFYBh-.js +46 -0
- package/dist/renderer/assets/{input-DqVQNCx_.js → input-CoWcfa8u.js} +2 -2
- package/dist/renderer/assets/ipc-transport-Cd2xPrsa.js +9 -0
- package/dist/renderer/assets/popover-Nq5gT9DO.js +2 -0
- package/dist/renderer/assets/select-By5KH-UG.js +2 -0
- package/dist/renderer/assets/{settings-BFNfnYvU.js → settings-Dj_N70qR.js} +2 -2
- package/dist/renderer/assets/settings-api-Do0_Smq1.js +2 -0
- package/dist/renderer/assets/workbenchSettings-CazSLGYt.js +8 -0
- package/dist/renderer/entries/main/index.html +5 -4
- package/dist/renderer/entries/popover/index.html +5 -4
- package/dist/renderer/entries/settings/index.html +4 -4
- package/dist/renderer/entries/workbench-settings/index.html +4 -3
- package/dist/shared/ipc-channels.d.ts +4 -12
- package/dist/shared/ipc-channels.js +10 -14
- package/dist/shared/simulator-route.d.ts +72 -0
- package/dist/shared/simulator-route.js +169 -0
- package/dist/shared/types.d.ts +2 -10
- package/dist/simulator/assets/simulator-DJCozrU5.js +9 -0
- package/dist/simulator/simulator.html +6 -43
- package/package.json +4 -4
- package/dist/preload/instrumentation/disposable.d.ts +0 -11
- package/dist/preload/instrumentation/disposable.js +0 -15
- package/dist/renderer/assets/index-Czz_bp6b.js +0 -46
- package/dist/renderer/assets/ipc-transport-CCHrCtDr.js +0 -9
- package/dist/renderer/assets/popover-BRg4XI_w.js +0 -2
- package/dist/renderer/assets/select-CvILHHZU.js +0 -2
- package/dist/renderer/assets/settings-api-DOAgmBst.js +0 -2
- package/dist/renderer/assets/workbenchSettings-DjVMgMMH.js +0 -8
- package/dist/simulator/assets/simulator-DL6kOCq-.js +0 -9
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
// src/main/app/bootstrap.ts
|
|
2
2
|
import { app as app2 } from "electron";
|
|
3
3
|
|
|
4
|
+
// src/shared/constants.ts
|
|
5
|
+
var DEFAULT_CDP_PORT = 9222;
|
|
6
|
+
var DEFAULT_SCENE = 1001;
|
|
7
|
+
|
|
4
8
|
// src/main/services/settings/index.ts
|
|
5
9
|
import { app, nativeTheme } from "electron";
|
|
6
10
|
import fs from "fs";
|
|
@@ -8,7 +12,7 @@ import path from "path";
|
|
|
8
12
|
var DEFAULTS = {
|
|
9
13
|
cdp: {
|
|
10
14
|
enabled: false,
|
|
11
|
-
port:
|
|
15
|
+
port: DEFAULT_CDP_PORT
|
|
12
16
|
},
|
|
13
17
|
mcp: {
|
|
14
18
|
enabled: false,
|
|
@@ -70,12 +74,12 @@ function setupCdpPort() {
|
|
|
70
74
|
if (settings.cdp.enabled || settings.mcp.enabled) {
|
|
71
75
|
app2.commandLine.appendSwitch("remote-debugging-port", String(settings.cdp.port));
|
|
72
76
|
} else if (!app2.isPackaged) {
|
|
73
|
-
app2.commandLine.appendSwitch("remote-debugging-port", String(settings.cdp.port ||
|
|
77
|
+
app2.commandLine.appendSwitch("remote-debugging-port", String(settings.cdp.port || DEFAULT_CDP_PORT));
|
|
74
78
|
}
|
|
75
79
|
}
|
|
76
80
|
|
|
77
81
|
// src/main/app/app.ts
|
|
78
|
-
import { app as app13, BrowserWindow as
|
|
82
|
+
import { app as app13, BrowserWindow as BrowserWindow4, nativeImage } from "electron";
|
|
79
83
|
import fs7 from "fs";
|
|
80
84
|
import path12 from "path";
|
|
81
85
|
|
|
@@ -103,6 +107,83 @@ var defaultPreloadPath = path2.join(devtoolsPackageRoot, "dist/preload/windows/s
|
|
|
103
107
|
var mainPreloadPath = path2.join(devtoolsPackageRoot, "dist/preload/windows/main.cjs");
|
|
104
108
|
var simulatorDir = path2.join(devtoolsPackageRoot, "dist/simulator");
|
|
105
109
|
|
|
110
|
+
// src/main/utils/theme.ts
|
|
111
|
+
import { BrowserWindow, nativeTheme as nativeTheme2 } from "electron";
|
|
112
|
+
|
|
113
|
+
// src/main/utils/disposable.ts
|
|
114
|
+
function toDisposable(fn) {
|
|
115
|
+
let done = false;
|
|
116
|
+
return {
|
|
117
|
+
dispose() {
|
|
118
|
+
if (done) return;
|
|
119
|
+
done = true;
|
|
120
|
+
return fn();
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
var DisposableRegistry = class {
|
|
125
|
+
entries = [];
|
|
126
|
+
_disposed = false;
|
|
127
|
+
add(d) {
|
|
128
|
+
if (this._disposed) {
|
|
129
|
+
throw new Error("cannot add to disposed registry");
|
|
130
|
+
}
|
|
131
|
+
const fn = typeof d === "function" ? d : () => d.dispose();
|
|
132
|
+
const entry = { fn, released: false };
|
|
133
|
+
this.entries.push(entry);
|
|
134
|
+
return {
|
|
135
|
+
dispose: () => {
|
|
136
|
+
if (entry.released) return;
|
|
137
|
+
entry.released = true;
|
|
138
|
+
const i = this.entries.indexOf(entry);
|
|
139
|
+
if (i >= 0) this.entries.splice(i, 1);
|
|
140
|
+
return fn();
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
async disposeAll() {
|
|
145
|
+
if (this._disposed) return;
|
|
146
|
+
this._disposed = true;
|
|
147
|
+
const items = this.entries.slice().reverse();
|
|
148
|
+
this.entries = [];
|
|
149
|
+
const errors = [];
|
|
150
|
+
for (const entry of items) {
|
|
151
|
+
if (entry.released) continue;
|
|
152
|
+
entry.released = true;
|
|
153
|
+
try {
|
|
154
|
+
await entry.fn();
|
|
155
|
+
} catch (e) {
|
|
156
|
+
errors.push(e);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (errors.length > 0) {
|
|
160
|
+
throw new AggregateError(errors, "DisposableRegistry encountered errors during disposeAll");
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
dispose() {
|
|
164
|
+
return this.disposeAll();
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// src/main/utils/theme.ts
|
|
169
|
+
function themeBg() {
|
|
170
|
+
return nativeTheme2.shouldUseDarkColors ? "#1a1a1a" : "#fafafa";
|
|
171
|
+
}
|
|
172
|
+
function installThemeBackgroundSync() {
|
|
173
|
+
const apply = () => {
|
|
174
|
+
const bg = themeBg();
|
|
175
|
+
for (const win of BrowserWindow.getAllWindows()) {
|
|
176
|
+
if (!win.isDestroyed()) {
|
|
177
|
+
win.setBackgroundColor(bg);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
nativeTheme2.on("updated", apply);
|
|
182
|
+
return toDisposable(() => {
|
|
183
|
+
nativeTheme2.removeListener("updated", apply);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
106
187
|
// src/main/app/lifecycle.ts
|
|
107
188
|
import { app as app3, globalShortcut } from "electron";
|
|
108
189
|
function registerAppLifecycle() {
|
|
@@ -116,7 +197,7 @@ function registerAppLifecycle() {
|
|
|
116
197
|
}
|
|
117
198
|
|
|
118
199
|
// src/main/windows/main-window/create.ts
|
|
119
|
-
import { app as app4, BrowserWindow, View, session, shell as shell2 } from "electron";
|
|
200
|
+
import { app as app4, BrowserWindow as BrowserWindow2, View, session, shell as shell2 } from "electron";
|
|
120
201
|
import path4 from "path";
|
|
121
202
|
|
|
122
203
|
// src/main/services/simulator/referer.ts
|
|
@@ -138,12 +219,6 @@ function getSimulatorServicewechatReferer() {
|
|
|
138
219
|
return cachedRefererUrl;
|
|
139
220
|
}
|
|
140
221
|
|
|
141
|
-
// src/main/utils/theme.ts
|
|
142
|
-
import { nativeTheme as nativeTheme2 } from "electron";
|
|
143
|
-
function themeBg() {
|
|
144
|
-
return nativeTheme2.shouldUseDarkColors ? "#1a1a1a" : "#fafafa";
|
|
145
|
-
}
|
|
146
|
-
|
|
147
222
|
// src/main/windows/navigation-hardening.ts
|
|
148
223
|
import { shell } from "electron";
|
|
149
224
|
import path3 from "path";
|
|
@@ -208,7 +283,7 @@ function configureSimulatorSession(simulatorPreloadPath) {
|
|
|
208
283
|
}
|
|
209
284
|
function createMainWindow(opts) {
|
|
210
285
|
configureSimulatorSession(opts.simulatorPreloadPath);
|
|
211
|
-
const mainWindow = new
|
|
286
|
+
const mainWindow = new BrowserWindow2({
|
|
212
287
|
width: opts.width ?? 1280,
|
|
213
288
|
height: opts.height ?? 980,
|
|
214
289
|
minWidth: opts.minWidth ?? 1e3,
|
|
@@ -274,63 +349,6 @@ function createMainWindow(opts) {
|
|
|
274
349
|
|
|
275
350
|
// src/main/windows/main-window/events.ts
|
|
276
351
|
import { globalShortcut as globalShortcut2 } from "electron";
|
|
277
|
-
|
|
278
|
-
// src/main/utils/disposable.ts
|
|
279
|
-
function toDisposable(fn) {
|
|
280
|
-
let done = false;
|
|
281
|
-
return {
|
|
282
|
-
dispose() {
|
|
283
|
-
if (done) return;
|
|
284
|
-
done = true;
|
|
285
|
-
return fn();
|
|
286
|
-
}
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
var DisposableRegistry = class {
|
|
290
|
-
entries = [];
|
|
291
|
-
_disposed = false;
|
|
292
|
-
add(d) {
|
|
293
|
-
if (this._disposed) {
|
|
294
|
-
throw new Error("cannot add to disposed registry");
|
|
295
|
-
}
|
|
296
|
-
const fn = typeof d === "function" ? d : () => d.dispose();
|
|
297
|
-
const entry = { fn, released: false };
|
|
298
|
-
this.entries.push(entry);
|
|
299
|
-
return {
|
|
300
|
-
dispose: () => {
|
|
301
|
-
if (entry.released) return;
|
|
302
|
-
entry.released = true;
|
|
303
|
-
const i = this.entries.indexOf(entry);
|
|
304
|
-
if (i >= 0) this.entries.splice(i, 1);
|
|
305
|
-
return fn();
|
|
306
|
-
}
|
|
307
|
-
};
|
|
308
|
-
}
|
|
309
|
-
async disposeAll() {
|
|
310
|
-
if (this._disposed) return;
|
|
311
|
-
this._disposed = true;
|
|
312
|
-
const items = this.entries.slice().reverse();
|
|
313
|
-
this.entries = [];
|
|
314
|
-
const errors = [];
|
|
315
|
-
for (const entry of items) {
|
|
316
|
-
if (entry.released) continue;
|
|
317
|
-
entry.released = true;
|
|
318
|
-
try {
|
|
319
|
-
await entry.fn();
|
|
320
|
-
} catch (e) {
|
|
321
|
-
errors.push(e);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
if (errors.length > 0) {
|
|
325
|
-
throw new AggregateError(errors, "DisposableRegistry encountered errors during disposeAll");
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
dispose() {
|
|
329
|
-
return this.disposeAll();
|
|
330
|
-
}
|
|
331
|
-
};
|
|
332
|
-
|
|
333
|
-
// src/main/windows/main-window/events.ts
|
|
334
352
|
function wireMainWindowEvents(win, state = {}) {
|
|
335
353
|
const registry = new DisposableRegistry();
|
|
336
354
|
const mainWebView = win.contentView.children[0];
|
|
@@ -387,12 +405,12 @@ import { app as app5 } from "electron";
|
|
|
387
405
|
var defaultAdapter = {
|
|
388
406
|
async openProject(opts) {
|
|
389
407
|
const diminaKit = await import("@dimina-kit/devkit");
|
|
390
|
-
const
|
|
391
|
-
return openProject({
|
|
408
|
+
const openProjectOpts = {
|
|
392
409
|
outputDir: path5.join(app5.getPath("userData"), "dimina-fe-output"),
|
|
393
410
|
...opts,
|
|
394
411
|
simulatorDir
|
|
395
|
-
}
|
|
412
|
+
};
|
|
413
|
+
return diminaKit.openProject(openProjectOpts);
|
|
396
414
|
}
|
|
397
415
|
};
|
|
398
416
|
|
|
@@ -402,10 +420,7 @@ var SimulatorChannel = {
|
|
|
402
420
|
Detach: "simulator:detach",
|
|
403
421
|
Resize: "simulator:resize",
|
|
404
422
|
SetVisible: "simulator:setVisible",
|
|
405
|
-
Console: "simulator:console"
|
|
406
|
-
Wxml: "simulator:wxml",
|
|
407
|
-
AppData: "simulator:appdata",
|
|
408
|
-
AppDataAll: "simulator:appdata-all"
|
|
423
|
+
Console: "simulator:console"
|
|
409
424
|
};
|
|
410
425
|
var SimulatorCustomApiChannel = {
|
|
411
426
|
List: "simulator:custom-apis:list",
|
|
@@ -424,16 +439,12 @@ var SimulatorElementChannel = {
|
|
|
424
439
|
Inspect: "simulator:element:inspect",
|
|
425
440
|
Clear: "simulator:element:clear"
|
|
426
441
|
};
|
|
427
|
-
var WorkbenchChannel = {
|
|
428
|
-
GetPanelConfig: "workbench:getPanelConfig",
|
|
429
|
-
GetApiNamespaces: "workbench:getApiNamespaces",
|
|
430
|
-
Reset: "workbench:reset"
|
|
431
|
-
};
|
|
432
442
|
var WorkbenchSettingsChannel = {
|
|
433
443
|
Get: "workbenchSettings:get",
|
|
434
444
|
Save: "workbenchSettings:save",
|
|
435
445
|
SetTheme: "workbenchSettings:setTheme",
|
|
436
446
|
GetCdpStatus: "workbenchSettings:getCdpStatus",
|
|
447
|
+
GetMcpStatus: "workbenchSettings:getMcpStatus",
|
|
437
448
|
SetVisible: "workbenchSettings:setVisible",
|
|
438
449
|
Init: "workbenchSettings:init"
|
|
439
450
|
};
|
|
@@ -516,8 +527,8 @@ function liveWebContents(wc) {
|
|
|
516
527
|
}
|
|
517
528
|
function createRendererNotifier(ctx) {
|
|
518
529
|
function sendToMain(channel, ...args) {
|
|
519
|
-
if (ctx.mainWindow.isDestroyed()) return;
|
|
520
|
-
const wc = liveWebContents(ctx.mainWindow.webContents);
|
|
530
|
+
if (ctx.windows.mainWindow.isDestroyed()) return;
|
|
531
|
+
const wc = liveWebContents(ctx.windows.mainWindow.webContents);
|
|
521
532
|
if (!wc) return;
|
|
522
533
|
wc.send(channel, ...args);
|
|
523
534
|
}
|
|
@@ -540,9 +551,6 @@ function createRendererNotifier(ctx) {
|
|
|
540
551
|
popoverRelaunch(config) {
|
|
541
552
|
sendToMain(PopoverChannel.Relaunch, config);
|
|
542
553
|
},
|
|
543
|
-
workbenchReset() {
|
|
544
|
-
sendToMain(WorkbenchChannel.Reset);
|
|
545
|
-
},
|
|
546
554
|
toolbarActionsChanged() {
|
|
547
555
|
sendToMain(ToolbarChannel.ActionsChanged);
|
|
548
556
|
},
|
|
@@ -616,9 +624,9 @@ function createViewManager(ctx) {
|
|
|
616
624
|
let simulatorWebContentsId = null;
|
|
617
625
|
function destroyViewInternal(view) {
|
|
618
626
|
if (!view) return;
|
|
619
|
-
if (!ctx.mainWindow.isDestroyed()) {
|
|
627
|
+
if (!ctx.windows.mainWindow.isDestroyed()) {
|
|
620
628
|
try {
|
|
621
|
-
ctx.mainWindow.contentView.removeChildView(view);
|
|
629
|
+
ctx.windows.mainWindow.contentView.removeChildView(view);
|
|
622
630
|
} catch {
|
|
623
631
|
}
|
|
624
632
|
}
|
|
@@ -630,18 +638,18 @@ function createViewManager(ctx) {
|
|
|
630
638
|
}
|
|
631
639
|
}
|
|
632
640
|
function applySimulatorBounds(simWidth) {
|
|
633
|
-
if (!simulatorView || ctx.mainWindow.isDestroyed()) return;
|
|
634
|
-
const [w = 0, h = 0] = ctx.mainWindow.getContentSize();
|
|
641
|
+
if (!simulatorView || ctx.windows.mainWindow.isDestroyed()) return;
|
|
642
|
+
const [w = 0, h = 0] = ctx.windows.mainWindow.getContentSize();
|
|
635
643
|
simulatorView.setBounds(computeSimulatorBounds(w, h, simWidth));
|
|
636
644
|
}
|
|
637
645
|
function applySettingsBounds() {
|
|
638
|
-
if (!settingsView || ctx.mainWindow.isDestroyed()) return;
|
|
639
|
-
const [w = 0, h = 0] = ctx.mainWindow.getContentSize();
|
|
646
|
+
if (!settingsView || ctx.windows.mainWindow.isDestroyed()) return;
|
|
647
|
+
const [w = 0, h = 0] = ctx.windows.mainWindow.getContentSize();
|
|
640
648
|
settingsView.setBounds(computeSettingsBounds(w, h));
|
|
641
649
|
}
|
|
642
650
|
function applyPopoverBounds() {
|
|
643
|
-
if (!popoverView || ctx.mainWindow.isDestroyed()) return;
|
|
644
|
-
const [w = 0, h = 0] = ctx.mainWindow.getContentSize();
|
|
651
|
+
if (!popoverView || ctx.windows.mainWindow.isDestroyed()) return;
|
|
652
|
+
const [w = 0, h = 0] = ctx.windows.mainWindow.getContentSize();
|
|
645
653
|
popoverView.setBounds(computePopoverBounds(w, h));
|
|
646
654
|
}
|
|
647
655
|
function attachSimulator(simWcId, simWidth) {
|
|
@@ -689,7 +697,7 @@ function createViewManager(ctx) {
|
|
|
689
697
|
});
|
|
690
698
|
});
|
|
691
699
|
if (getDefaultTab(ctx) === "simulator") {
|
|
692
|
-
ctx.mainWindow.contentView.addChildView(simulatorView);
|
|
700
|
+
ctx.windows.mainWindow.contentView.addChildView(simulatorView);
|
|
693
701
|
simulatorViewAdded = true;
|
|
694
702
|
applySimulatorBounds(simWidth);
|
|
695
703
|
}
|
|
@@ -708,7 +716,7 @@ function createViewManager(ctx) {
|
|
|
708
716
|
lastSimWidth = simWidth;
|
|
709
717
|
if (!simulatorView) return;
|
|
710
718
|
if (!simulatorViewAdded) {
|
|
711
|
-
ctx.mainWindow.contentView.addChildView(simulatorView);
|
|
719
|
+
ctx.windows.mainWindow.contentView.addChildView(simulatorView);
|
|
712
720
|
simulatorViewAdded = true;
|
|
713
721
|
}
|
|
714
722
|
applySimulatorBounds(simWidth);
|
|
@@ -716,7 +724,7 @@ function createViewManager(ctx) {
|
|
|
716
724
|
function hideSimulator() {
|
|
717
725
|
if (simulatorView && simulatorViewAdded) {
|
|
718
726
|
try {
|
|
719
|
-
ctx.mainWindow.contentView.removeChildView(simulatorView);
|
|
727
|
+
ctx.windows.mainWindow.contentView.removeChildView(simulatorView);
|
|
720
728
|
} catch (e) {
|
|
721
729
|
console.error("[workbench] hideSimulator error", e);
|
|
722
730
|
}
|
|
@@ -739,7 +747,7 @@ function createViewManager(ctx) {
|
|
|
739
747
|
);
|
|
740
748
|
}
|
|
741
749
|
if (!settingsViewAdded) {
|
|
742
|
-
ctx.mainWindow.contentView.addChildView(settingsView);
|
|
750
|
+
ctx.windows.mainWindow.contentView.addChildView(settingsView);
|
|
743
751
|
settingsViewAdded = true;
|
|
744
752
|
}
|
|
745
753
|
applySettingsBounds();
|
|
@@ -747,7 +755,7 @@ function createViewManager(ctx) {
|
|
|
747
755
|
function hideSettings() {
|
|
748
756
|
if (settingsView && settingsViewAdded) {
|
|
749
757
|
try {
|
|
750
|
-
ctx.mainWindow.contentView.removeChildView(settingsView);
|
|
758
|
+
ctx.windows.mainWindow.contentView.removeChildView(settingsView);
|
|
751
759
|
} catch {
|
|
752
760
|
}
|
|
753
761
|
settingsViewAdded = false;
|
|
@@ -766,7 +774,7 @@ function createViewManager(ctx) {
|
|
|
766
774
|
applyNavigationHardening(popover.webContents, ctx.rendererDir);
|
|
767
775
|
popoverView = popover;
|
|
768
776
|
popover.setBackgroundColor("#00000000");
|
|
769
|
-
ctx.mainWindow.contentView.addChildView(popover);
|
|
777
|
+
ctx.windows.mainWindow.contentView.addChildView(popover);
|
|
770
778
|
applyPopoverBounds();
|
|
771
779
|
popover.webContents.once("did-finish-load", () => {
|
|
772
780
|
ctx.notify.popoverInit(popover, data);
|
|
@@ -793,14 +801,6 @@ function createViewManager(ctx) {
|
|
|
793
801
|
function disposeAll() {
|
|
794
802
|
detachSimulator();
|
|
795
803
|
}
|
|
796
|
-
function logChildViews(_label) {
|
|
797
|
-
}
|
|
798
|
-
function positionSimulator(simWidth) {
|
|
799
|
-
applySimulatorBounds(simWidth);
|
|
800
|
-
}
|
|
801
|
-
function positionSettings() {
|
|
802
|
-
applySettingsBounds();
|
|
803
|
-
}
|
|
804
804
|
function resize(simWidth) {
|
|
805
805
|
lastSimWidth = simWidth;
|
|
806
806
|
if (simulatorViewAdded) applySimulatorBounds(simWidth);
|
|
@@ -826,10 +826,12 @@ function createViewManager(ctx) {
|
|
|
826
826
|
hidePopover,
|
|
827
827
|
repositionAll,
|
|
828
828
|
disposeAll,
|
|
829
|
-
logChildViews,
|
|
830
|
-
positionSimulator,
|
|
831
|
-
positionSettings,
|
|
832
829
|
getSimulatorWebContentsId: () => simulatorWebContentsId,
|
|
830
|
+
getSimulatorWebContents: () => {
|
|
831
|
+
if (simulatorWebContentsId == null) return null;
|
|
832
|
+
const wc = webContents.fromId(simulatorWebContentsId);
|
|
833
|
+
return wc && !wc.isDestroyed() ? wc : null;
|
|
834
|
+
},
|
|
833
835
|
getLastSimWidth: () => lastSimWidth,
|
|
834
836
|
isSimulatorAdded: () => simulatorViewAdded,
|
|
835
837
|
hasSimulatorView: () => simulatorView !== null,
|
|
@@ -879,17 +881,11 @@ function createWindowService(mainWindow) {
|
|
|
879
881
|
};
|
|
880
882
|
}
|
|
881
883
|
|
|
882
|
-
// src/main/services/workspace/workspace-service.ts
|
|
883
|
-
import { webContents as webContents2 } from "electron";
|
|
884
|
-
|
|
885
884
|
// src/main/services/projects/project-repository.ts
|
|
886
885
|
import { app as app6 } from "electron";
|
|
887
886
|
import path7 from "path";
|
|
888
887
|
import fs3 from "fs";
|
|
889
888
|
|
|
890
|
-
// src/shared/constants.ts
|
|
891
|
-
var DEFAULT_SCENE = 1001;
|
|
892
|
-
|
|
893
889
|
// src/main/utils/logger.ts
|
|
894
890
|
var LEVEL_PRIORITY = {
|
|
895
891
|
debug: 0,
|
|
@@ -1077,8 +1073,8 @@ var DEFAULT_COMPILE_CONFIG = {
|
|
|
1077
1073
|
function createWorkspaceService(ctx) {
|
|
1078
1074
|
let currentSession = null;
|
|
1079
1075
|
let currentProjectPath = "";
|
|
1080
|
-
function sendStatus(
|
|
1081
|
-
ctx.notify.projectStatus(hotReload ? { status, message, hotReload: true } : { status, message });
|
|
1076
|
+
function sendStatus(status2, message, hotReload) {
|
|
1077
|
+
ctx.notify.projectStatus(hotReload ? { status: status2, message, hotReload: true } : { status: status2, message });
|
|
1082
1078
|
}
|
|
1083
1079
|
function bestEffort(label, fn) {
|
|
1084
1080
|
try {
|
|
@@ -1111,15 +1107,7 @@ function createWorkspaceService(ctx) {
|
|
|
1111
1107
|
);
|
|
1112
1108
|
}
|
|
1113
1109
|
}
|
|
1114
|
-
const provider = ctx.projectsProvider
|
|
1115
|
-
listProjects: () => listProjects(),
|
|
1116
|
-
addProject: (p) => addProject(p),
|
|
1117
|
-
removeProject: (p) => removeProject(p),
|
|
1118
|
-
validateProjectDir: (p) => validateProjectDir(p),
|
|
1119
|
-
updateLastOpened: (p) => updateLastOpened(p),
|
|
1120
|
-
getCompileConfig: (p) => getCompileConfig(p),
|
|
1121
|
-
saveCompileConfig: (p, c) => saveCompileConfig(p, c)
|
|
1122
|
-
};
|
|
1110
|
+
const provider = ctx.projectsProvider;
|
|
1123
1111
|
return {
|
|
1124
1112
|
listProjects: async () => provider.listProjects(),
|
|
1125
1113
|
addProject: async (dirPath) => provider.addProject(dirPath),
|
|
@@ -1179,10 +1167,8 @@ function createWorkspaceService(ctx) {
|
|
|
1179
1167
|
getProjectPath: () => currentProjectPath,
|
|
1180
1168
|
hasActiveSession: () => currentSession !== null,
|
|
1181
1169
|
async captureThumbnail(projectPath) {
|
|
1182
|
-
const
|
|
1183
|
-
if (!
|
|
1184
|
-
const wc = webContents2.fromId(simWcId);
|
|
1185
|
-
if (!wc || wc.isDestroyed()) return null;
|
|
1170
|
+
const wc = ctx.views.getSimulatorWebContents();
|
|
1171
|
+
if (!wc) return null;
|
|
1186
1172
|
try {
|
|
1187
1173
|
const image = await wc.capturePage();
|
|
1188
1174
|
const dataUrl = `data:image/png;base64,${image.toPNG().toString("base64")}`;
|
|
@@ -1317,7 +1303,6 @@ function getDefaultTab(ctx) {
|
|
|
1317
1303
|
}
|
|
1318
1304
|
function createWorkbenchContext(opts) {
|
|
1319
1305
|
const ctx = {
|
|
1320
|
-
mainWindow: opts.mainWindow,
|
|
1321
1306
|
adapter: opts.adapter ?? defaultAdapter,
|
|
1322
1307
|
preloadPath: opts.preloadPath,
|
|
1323
1308
|
rendererDir: opts.rendererDir,
|
|
@@ -1325,11 +1310,10 @@ function createWorkbenchContext(opts) {
|
|
|
1325
1310
|
apiNamespaces: opts.apiNamespaces ?? [],
|
|
1326
1311
|
appName: opts.appName ?? "Dimina DevTools",
|
|
1327
1312
|
toolbarActions: opts.toolbarActions,
|
|
1328
|
-
brandingProvider: opts.brandingProvider
|
|
1329
|
-
workbenchSettingsWindow: null
|
|
1313
|
+
brandingProvider: opts.brandingProvider
|
|
1330
1314
|
};
|
|
1331
1315
|
ctx.registry = new DisposableRegistry();
|
|
1332
|
-
ctx.windows = createWindowService(
|
|
1316
|
+
ctx.windows = createWindowService(opts.mainWindow);
|
|
1333
1317
|
ctx.views = createViewManager(ctx);
|
|
1334
1318
|
ctx.notify = createRendererNotifier(ctx);
|
|
1335
1319
|
ctx.projectsProvider = opts.projectsProvider ?? createLocalProjectsProvider();
|
|
@@ -1644,17 +1628,10 @@ function registerSimulatorIpc(ctx) {
|
|
|
1644
1628
|
}).handle(SimulatorCustomApiChannel.Invoke, (_, ...args) => {
|
|
1645
1629
|
const [name, params] = validate(SimulatorCustomApiChannel.Invoke, SimulatorCustomApiInvokeSchema, args);
|
|
1646
1630
|
return simulatorApiRegistry.invoke(name, params);
|
|
1647
|
-
}).handle(WorkbenchChannel.GetPanelConfig, () => {
|
|
1648
|
-
return ctx.panels;
|
|
1649
|
-
}).handle(WorkbenchChannel.GetApiNamespaces, () => {
|
|
1650
|
-
return ctx.apiNamespaces;
|
|
1651
|
-
}).on(WorkbenchChannel.Reset, () => {
|
|
1652
|
-
ctx.notify.workbenchReset();
|
|
1653
1631
|
});
|
|
1654
1632
|
}
|
|
1655
1633
|
|
|
1656
1634
|
// src/main/ipc/panels.ts
|
|
1657
|
-
import { webContents as webContents3 } from "electron";
|
|
1658
1635
|
var BUILTIN_PANELS = [
|
|
1659
1636
|
{ id: "wxml", label: "WXML" },
|
|
1660
1637
|
{ id: "appdata", label: "AppData" },
|
|
@@ -1665,10 +1642,9 @@ function registerPanelsIpc(ctx) {
|
|
|
1665
1642
|
return BUILTIN_PANELS.filter((p) => ctx.panels.includes(p.id));
|
|
1666
1643
|
}).handle(PanelChannel.Eval, async (_event, ...args) => {
|
|
1667
1644
|
const [expression] = validate(PanelChannel.Eval, PanelEvalSchema, args);
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
if (!sim || sim.isDestroyed()) return void 0;
|
|
1645
|
+
if (!ctx.workspace.hasActiveSession()) return void 0;
|
|
1646
|
+
const sim = ctx.views.getSimulatorWebContents();
|
|
1647
|
+
if (!sim) return void 0;
|
|
1672
1648
|
try {
|
|
1673
1649
|
return await sim.executeJavaScript(expression);
|
|
1674
1650
|
} catch {
|
|
@@ -1776,7 +1752,7 @@ function registerProjectsIpc(ctx) {
|
|
|
1776
1752
|
return new IpcRegistry(ctx.senderPolicy).handle(ProjectsChannel.List, () => {
|
|
1777
1753
|
return ctx.workspace.listProjects();
|
|
1778
1754
|
}).handle(DialogChannel.OpenDirectory, async () => {
|
|
1779
|
-
const result = await dialog.showOpenDialog(ctx.mainWindow, {
|
|
1755
|
+
const result = await dialog.showOpenDialog(ctx.windows.mainWindow, {
|
|
1780
1756
|
properties: ["openDirectory"],
|
|
1781
1757
|
title: "\u9009\u62E9\u5C0F\u7A0B\u5E8F\u9879\u76EE\u76EE\u5F55"
|
|
1782
1758
|
});
|
|
@@ -1785,7 +1761,7 @@ function registerProjectsIpc(ctx) {
|
|
|
1785
1761
|
const [dirPath] = validate(ProjectsChannel.Add, ProjectsAddSchema, args);
|
|
1786
1762
|
const dirError = await ctx.workspace.validateProjectDir(dirPath);
|
|
1787
1763
|
if (dirError) {
|
|
1788
|
-
await dialog.showMessageBox(ctx.mainWindow, {
|
|
1764
|
+
await dialog.showMessageBox(ctx.windows.mainWindow, {
|
|
1789
1765
|
type: "error",
|
|
1790
1766
|
title: "\u65E0\u6CD5\u5BFC\u5165\u9879\u76EE",
|
|
1791
1767
|
message: "\u8BE5\u76EE\u5F55\u4E0D\u662F\u6709\u6548\u7684\u5C0F\u7A0B\u5E8F\u9879\u76EE",
|
|
@@ -1797,7 +1773,7 @@ function registerProjectsIpc(ctx) {
|
|
|
1797
1773
|
const duplicate = await ctx.workspace.hasProject(dirPath);
|
|
1798
1774
|
const project = await ctx.workspace.addProject(dirPath);
|
|
1799
1775
|
if (duplicate) {
|
|
1800
|
-
await dialog.showMessageBox(ctx.mainWindow, {
|
|
1776
|
+
await dialog.showMessageBox(ctx.windows.mainWindow, {
|
|
1801
1777
|
type: "info",
|
|
1802
1778
|
title: "\u9879\u76EE\u5DF2\u5B58\u5728",
|
|
1803
1779
|
message: "\u8BE5\u9879\u76EE\u5DF2\u5728\u5217\u8868\u4E2D",
|
|
@@ -1815,7 +1791,7 @@ function registerProjectsIpc(ctx) {
|
|
|
1815
1791
|
if (!ctx.customCreateProjectDialog) return null;
|
|
1816
1792
|
const sanitized = sanitizeTemplates(ctx.projectTemplates ?? []);
|
|
1817
1793
|
return await ctx.customCreateProjectDialog({
|
|
1818
|
-
parentWindow: ctx.mainWindow,
|
|
1794
|
+
parentWindow: ctx.windows.mainWindow,
|
|
1819
1795
|
templates: sanitized
|
|
1820
1796
|
});
|
|
1821
1797
|
}).handle(ProjectsChannel.Create, async (_event, ...args) => {
|
|
@@ -1831,7 +1807,7 @@ function registerProjectsIpc(ctx) {
|
|
|
1831
1807
|
projectsProvider: ctx.projectsProvider
|
|
1832
1808
|
});
|
|
1833
1809
|
} catch (err) {
|
|
1834
|
-
await dialog.showMessageBox(ctx.mainWindow, {
|
|
1810
|
+
await dialog.showMessageBox(ctx.windows.mainWindow, {
|
|
1835
1811
|
type: "error",
|
|
1836
1812
|
title: "\u521B\u5EFA\u9879\u76EE\u5931\u8D25",
|
|
1837
1813
|
message: "\u65E0\u6CD5\u521B\u5EFA\u9879\u76EE",
|
|
@@ -1913,6 +1889,23 @@ var sessionModule = {
|
|
|
1913
1889
|
|
|
1914
1890
|
// src/main/ipc/settings.ts
|
|
1915
1891
|
import { app as app9 } from "electron";
|
|
1892
|
+
|
|
1893
|
+
// src/main/services/mcp/status.ts
|
|
1894
|
+
var status = { running: false, port: null, error: null };
|
|
1895
|
+
function getMcpStatus() {
|
|
1896
|
+
return { ...status };
|
|
1897
|
+
}
|
|
1898
|
+
function recordMcpStarted(port) {
|
|
1899
|
+
status = { running: true, port, error: null };
|
|
1900
|
+
}
|
|
1901
|
+
function recordMcpFailed(error) {
|
|
1902
|
+
status = { running: false, port: null, error };
|
|
1903
|
+
}
|
|
1904
|
+
function recordMcpStopped() {
|
|
1905
|
+
status = { running: false, port: null, error: null };
|
|
1906
|
+
}
|
|
1907
|
+
|
|
1908
|
+
// src/main/ipc/settings.ts
|
|
1916
1909
|
function registerSettingsIpc(ctx) {
|
|
1917
1910
|
return new IpcRegistry(ctx.senderPolicy).handle(WorkbenchSettingsChannel.Get, () => {
|
|
1918
1911
|
return loadWorkbenchSettings();
|
|
@@ -1935,7 +1928,7 @@ function registerSettingsIpc(ctx) {
|
|
|
1935
1928
|
}).handle(WorkbenchSettingsChannel.GetCdpStatus, () => {
|
|
1936
1929
|
const settings = loadWorkbenchSettings();
|
|
1937
1930
|
const switchValue = app9.commandLine.getSwitchValue("remote-debugging-port");
|
|
1938
|
-
const implicitDevDefault = !app9.isPackaged && !settings.cdp.enabled && switchValue ===
|
|
1931
|
+
const implicitDevDefault = !app9.isPackaged && !settings.cdp.enabled && switchValue === String(DEFAULT_CDP_PORT);
|
|
1939
1932
|
return {
|
|
1940
1933
|
configured: settings.cdp.enabled,
|
|
1941
1934
|
port: settings.cdp.port,
|
|
@@ -1943,6 +1936,16 @@ function registerSettingsIpc(ctx) {
|
|
|
1943
1936
|
activePort: switchValue ? parseInt(switchValue, 10) : null,
|
|
1944
1937
|
implicitDevDefault
|
|
1945
1938
|
};
|
|
1939
|
+
}).handle(WorkbenchSettingsChannel.GetMcpStatus, () => {
|
|
1940
|
+
const settings = loadWorkbenchSettings();
|
|
1941
|
+
const runtime = getMcpStatus();
|
|
1942
|
+
return {
|
|
1943
|
+
configured: settings.mcp.enabled,
|
|
1944
|
+
configuredPort: settings.mcp.port,
|
|
1945
|
+
running: runtime.running,
|
|
1946
|
+
activePort: runtime.port,
|
|
1947
|
+
error: runtime.error
|
|
1948
|
+
};
|
|
1946
1949
|
}).handle(WorkbenchSettingsChannel.SetVisible, async (_, ...args) => {
|
|
1947
1950
|
const [visible] = validate(
|
|
1948
1951
|
WorkbenchSettingsChannel.SetVisible,
|
|
@@ -2018,13 +2021,9 @@ var simulatorModule = {
|
|
|
2018
2021
|
import { WebSocketServer } from "ws";
|
|
2019
2022
|
|
|
2020
2023
|
// src/main/services/automation/exec.ts
|
|
2021
|
-
import { webContents as webContents4 } from "electron";
|
|
2022
2024
|
function getSimulator(ctx) {
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
const sim = webContents4.fromId(simWcId);
|
|
2026
|
-
if (!sim || sim.isDestroyed()) return null;
|
|
2027
|
-
return sim;
|
|
2025
|
+
if (!ctx.workspace.hasActiveSession()) return null;
|
|
2026
|
+
return ctx.views.getSimulatorWebContents();
|
|
2028
2027
|
}
|
|
2029
2028
|
async function evalInSim(ctx, expression) {
|
|
2030
2029
|
const sim = getSimulator(ctx);
|
|
@@ -2032,8 +2031,11 @@ async function evalInSim(ctx, expression) {
|
|
|
2032
2031
|
return sim.executeJavaScript(expression);
|
|
2033
2032
|
}
|
|
2034
2033
|
function buildElAccess(ref, varName = "el") {
|
|
2035
|
-
const
|
|
2036
|
-
|
|
2034
|
+
return `const ${varName} = _doc.querySelectorAll(${JSON.stringify(ref.selector)})[${ref.index}]`;
|
|
2035
|
+
}
|
|
2036
|
+
function evalInElement(ctx, ref, body, varName = "el") {
|
|
2037
|
+
return evalInSim(ctx, inIframe(`${buildElAccess(ref, varName)}
|
|
2038
|
+
${body}`));
|
|
2037
2039
|
}
|
|
2038
2040
|
function inIframe(code) {
|
|
2039
2041
|
return `(() => {
|
|
@@ -2053,47 +2055,57 @@ toolHandlers["Tool.close"] = async (ctx) => {
|
|
|
2053
2055
|
return {};
|
|
2054
2056
|
};
|
|
2055
2057
|
|
|
2058
|
+
// src/shared/simulator-route.ts
|
|
2059
|
+
function decodePageSpec(value) {
|
|
2060
|
+
const qIdx = value.indexOf("?");
|
|
2061
|
+
if (qIdx < 0) return { pagePath: value, query: {} };
|
|
2062
|
+
const pagePath = value.slice(0, qIdx);
|
|
2063
|
+
const query = {};
|
|
2064
|
+
for (const pair of value.slice(qIdx + 1).split("&")) {
|
|
2065
|
+
if (!pair) continue;
|
|
2066
|
+
const eqIdx = pair.indexOf("=");
|
|
2067
|
+
const k = eqIdx >= 0 ? pair.slice(0, eqIdx) : pair;
|
|
2068
|
+
const v = eqIdx >= 0 ? pair.slice(eqIdx + 1) : "";
|
|
2069
|
+
if (k) query[decodeURIComponent(k)] = decodeURIComponent(v);
|
|
2070
|
+
}
|
|
2071
|
+
return { pagePath, query };
|
|
2072
|
+
}
|
|
2073
|
+
function parseLocationRoute(search) {
|
|
2074
|
+
const params = new URLSearchParams(search.startsWith("?") ? search.slice(1) : search);
|
|
2075
|
+
const appId = params.get("appId");
|
|
2076
|
+
const entryRaw = params.get("entry");
|
|
2077
|
+
if (!appId || !entryRaw) return null;
|
|
2078
|
+
const entry = decodePageSpec(entryRaw);
|
|
2079
|
+
const pageRaw = params.get("page");
|
|
2080
|
+
const current = pageRaw && pageRaw !== entryRaw ? decodePageSpec(pageRaw) : entry;
|
|
2081
|
+
return { appId, entry, current };
|
|
2082
|
+
}
|
|
2083
|
+
|
|
2056
2084
|
// src/main/services/automation/handlers/app.ts
|
|
2057
2085
|
var appHandlers = {};
|
|
2086
|
+
async function readRoute(ctx) {
|
|
2087
|
+
const { search } = await evalInSim(
|
|
2088
|
+
ctx,
|
|
2089
|
+
`({ search: location.search })`
|
|
2090
|
+
);
|
|
2091
|
+
return parseLocationRoute(search);
|
|
2092
|
+
}
|
|
2058
2093
|
appHandlers["App.getCurrentPage"] = async (ctx) => {
|
|
2059
|
-
const
|
|
2060
|
-
const clean = hash.replace(/^#/, "");
|
|
2061
|
-
const qIdx = clean.indexOf("?");
|
|
2062
|
-
const pathPart = qIdx >= 0 ? clean.substring(0, qIdx) : clean;
|
|
2063
|
-
const queryPart = qIdx >= 0 ? clean.substring(qIdx + 1) : "";
|
|
2064
|
-
let pagePath;
|
|
2065
|
-
if (pathPart.includes("|")) {
|
|
2066
|
-
const parts = pathPart.split("|");
|
|
2067
|
-
pagePath = parts[parts.length - 1] ?? "";
|
|
2068
|
-
} else {
|
|
2069
|
-
const slashIdx = pathPart.indexOf("/");
|
|
2070
|
-
pagePath = slashIdx >= 0 ? pathPart.substring(slashIdx + 1) : pathPart;
|
|
2071
|
-
}
|
|
2072
|
-
const query = {};
|
|
2073
|
-
if (queryPart) {
|
|
2074
|
-
for (const pair of queryPart.split("&")) {
|
|
2075
|
-
const [k, v] = pair.split("=");
|
|
2076
|
-
if (k) query[k] = decodeURIComponent(v || "");
|
|
2077
|
-
}
|
|
2078
|
-
}
|
|
2094
|
+
const route = await readRoute(ctx);
|
|
2079
2095
|
const iframeCount = await evalInSim(ctx, `document.querySelectorAll('iframe').length`);
|
|
2080
|
-
return {
|
|
2096
|
+
return {
|
|
2097
|
+
pageId: iframeCount,
|
|
2098
|
+
path: route?.current.pagePath ?? "",
|
|
2099
|
+
query: route?.current.query ?? {}
|
|
2100
|
+
};
|
|
2081
2101
|
};
|
|
2082
2102
|
appHandlers["App.getPageStack"] = async (ctx) => {
|
|
2083
|
-
const
|
|
2084
|
-
const clean = hash.replace(/^#/, "").replace(/\?.*$/, "");
|
|
2103
|
+
const route = await readRoute(ctx);
|
|
2085
2104
|
const pageStack = [];
|
|
2086
|
-
if (
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
}
|
|
2091
|
-
} else {
|
|
2092
|
-
const slashIdx = clean.indexOf("/");
|
|
2093
|
-
const currentPath = slashIdx >= 0 ? clean.substring(slashIdx + 1) : clean;
|
|
2094
|
-
if (currentPath) {
|
|
2095
|
-
pageStack.push({ pageId: 1, path: currentPath, query: {} });
|
|
2096
|
-
}
|
|
2105
|
+
if (!route) return { pageStack };
|
|
2106
|
+
pageStack.push({ pageId: 1, path: route.entry.pagePath, query: route.entry.query });
|
|
2107
|
+
if (route.current.pagePath !== route.entry.pagePath) {
|
|
2108
|
+
pageStack.push({ pageId: 2, path: route.current.pagePath, query: route.current.query });
|
|
2097
2109
|
}
|
|
2098
2110
|
return { pageStack };
|
|
2099
2111
|
};
|
|
@@ -2106,18 +2118,29 @@ appHandlers["App.callWxMethod"] = async (ctx, params) => {
|
|
|
2106
2118
|
if (url) {
|
|
2107
2119
|
const cleanUrl = url.startsWith("/") ? url : `/${url}`;
|
|
2108
2120
|
const clicked = await evalInSim(ctx, inIframe(`
|
|
2109
|
-
const
|
|
2121
|
+
const path = ${JSON.stringify(cleanUrl)}
|
|
2122
|
+
const el = Array.from(_doc.querySelectorAll('[data-path]'))
|
|
2123
|
+
.find(e => e.getAttribute('data-path') === path)
|
|
2110
2124
|
if (el) { el.click(); return true }
|
|
2111
2125
|
return false
|
|
2112
2126
|
`)).catch(() => false);
|
|
2113
2127
|
if (!clicked) {
|
|
2114
|
-
const
|
|
2115
|
-
const
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2128
|
+
const apiName = JSON.stringify(method);
|
|
2129
|
+
const urlJson = JSON.stringify(cleanUrl);
|
|
2130
|
+
await evalInSim(
|
|
2131
|
+
ctx,
|
|
2132
|
+
`(() => {
|
|
2133
|
+
const iframes = Array.from(document.querySelectorAll('iframe'))
|
|
2134
|
+
for (const f of iframes) {
|
|
2135
|
+
try {
|
|
2136
|
+
if (f.contentWindow && f.contentWindow.wx && typeof f.contentWindow.wx[${apiName}] === 'function') {
|
|
2137
|
+
f.contentWindow.wx[${apiName}]({ url: ${urlJson} })
|
|
2138
|
+
return
|
|
2139
|
+
}
|
|
2140
|
+
} catch (_) {}
|
|
2141
|
+
}
|
|
2142
|
+
})()`
|
|
2143
|
+
);
|
|
2121
2144
|
}
|
|
2122
2145
|
await new Promise((r) => setTimeout(r, 2e3));
|
|
2123
2146
|
}
|
|
@@ -2252,109 +2275,97 @@ pageHandlers["Page.getWindowProperties"] = async (ctx, params) => {
|
|
|
2252
2275
|
var elementHandlers = {};
|
|
2253
2276
|
elementHandlers["Element.tap"] = async (ctx, params) => {
|
|
2254
2277
|
const ref = getElementRef(params);
|
|
2255
|
-
await
|
|
2256
|
-
${buildElAccess(ref)}
|
|
2278
|
+
await evalInElement(ctx, ref, `
|
|
2257
2279
|
if (!el) throw new Error('Element not found')
|
|
2258
2280
|
el.click()
|
|
2259
|
-
`)
|
|
2281
|
+
`);
|
|
2260
2282
|
return {};
|
|
2261
2283
|
};
|
|
2262
2284
|
elementHandlers["Element.triggerEvent"] = async (ctx, params) => {
|
|
2263
2285
|
const ref = getElementRef(params);
|
|
2264
2286
|
const type = params.type;
|
|
2265
2287
|
const detail = params.detail || {};
|
|
2266
|
-
await
|
|
2267
|
-
${buildElAccess(ref)}
|
|
2288
|
+
await evalInElement(ctx, ref, `
|
|
2268
2289
|
if (!el) throw new Error('Element not found')
|
|
2269
2290
|
el.dispatchEvent(new CustomEvent('${type}', { detail: ${JSON.stringify(detail)}, bubbles: true }))
|
|
2270
|
-
`)
|
|
2291
|
+
`);
|
|
2271
2292
|
return {};
|
|
2272
2293
|
};
|
|
2273
2294
|
elementHandlers["Element.touchstart"] = async (ctx, params) => {
|
|
2274
2295
|
const ref = getElementRef(params);
|
|
2275
|
-
await
|
|
2276
|
-
${buildElAccess(ref)}
|
|
2296
|
+
await evalInElement(ctx, ref, `
|
|
2277
2297
|
if (el) el.dispatchEvent(new TouchEvent('touchstart', { bubbles: true }))
|
|
2278
|
-
`)
|
|
2298
|
+
`);
|
|
2279
2299
|
return {};
|
|
2280
2300
|
};
|
|
2281
2301
|
elementHandlers["Element.touchmove"] = async (ctx, params) => {
|
|
2282
2302
|
const ref = getElementRef(params);
|
|
2283
|
-
await
|
|
2284
|
-
${buildElAccess(ref)}
|
|
2303
|
+
await evalInElement(ctx, ref, `
|
|
2285
2304
|
if (el) el.dispatchEvent(new TouchEvent('touchmove', { bubbles: true }))
|
|
2286
|
-
`)
|
|
2305
|
+
`);
|
|
2287
2306
|
return {};
|
|
2288
2307
|
};
|
|
2289
2308
|
elementHandlers["Element.touchend"] = async (ctx, params) => {
|
|
2290
2309
|
const ref = getElementRef(params);
|
|
2291
|
-
await
|
|
2292
|
-
${buildElAccess(ref)}
|
|
2310
|
+
await evalInElement(ctx, ref, `
|
|
2293
2311
|
if (el) el.dispatchEvent(new TouchEvent('touchend', { bubbles: true }))
|
|
2294
|
-
`)
|
|
2312
|
+
`);
|
|
2295
2313
|
return {};
|
|
2296
2314
|
};
|
|
2297
2315
|
elementHandlers["Element.getDOMProperties"] = async (ctx, params) => {
|
|
2298
2316
|
const ref = getElementRef(params);
|
|
2299
2317
|
const names = params.names;
|
|
2300
|
-
const properties = await
|
|
2301
|
-
${buildElAccess(ref)}
|
|
2318
|
+
const properties = await evalInElement(ctx, ref, `
|
|
2302
2319
|
if (!el) return ${JSON.stringify(names.map(() => null))}
|
|
2303
2320
|
return ${JSON.stringify(names)}.map(n => el[n])
|
|
2304
|
-
`)
|
|
2321
|
+
`);
|
|
2305
2322
|
return { properties };
|
|
2306
2323
|
};
|
|
2307
2324
|
elementHandlers["Element.getAttributes"] = async (ctx, params) => {
|
|
2308
2325
|
const ref = getElementRef(params);
|
|
2309
2326
|
const names = params.names;
|
|
2310
|
-
const attributes = await
|
|
2311
|
-
${buildElAccess(ref)}
|
|
2327
|
+
const attributes = await evalInElement(ctx, ref, `
|
|
2312
2328
|
if (!el) return ${JSON.stringify(names.map(() => null))}
|
|
2313
2329
|
return ${JSON.stringify(names)}.map(n => el.getAttribute(n))
|
|
2314
|
-
`)
|
|
2330
|
+
`);
|
|
2315
2331
|
return { attributes };
|
|
2316
2332
|
};
|
|
2317
2333
|
elementHandlers["Element.getStyles"] = async (ctx, params) => {
|
|
2318
2334
|
const ref = getElementRef(params);
|
|
2319
2335
|
const names = params.names;
|
|
2320
|
-
const styles = await
|
|
2321
|
-
${buildElAccess(ref)}
|
|
2336
|
+
const styles = await evalInElement(ctx, ref, `
|
|
2322
2337
|
if (!el) return ${JSON.stringify(names.map(() => ""))}
|
|
2323
2338
|
const cs = getComputedStyle(el)
|
|
2324
2339
|
return ${JSON.stringify(names)}.map(n => cs.getPropertyValue(n))
|
|
2325
|
-
`)
|
|
2340
|
+
`);
|
|
2326
2341
|
return { styles };
|
|
2327
2342
|
};
|
|
2328
2343
|
elementHandlers["Element.getWXML"] = async (ctx, params) => {
|
|
2329
2344
|
const ref = getElementRef(params);
|
|
2330
2345
|
const type = params.type || "inner";
|
|
2331
2346
|
const prop = type === "outer" ? "outerHTML" : "innerHTML";
|
|
2332
|
-
const wxml = await
|
|
2333
|
-
${buildElAccess(ref)}
|
|
2347
|
+
const wxml = await evalInElement(ctx, ref, `
|
|
2334
2348
|
return el ? el.${prop} : ''
|
|
2335
|
-
`)
|
|
2349
|
+
`);
|
|
2336
2350
|
return { wxml };
|
|
2337
2351
|
};
|
|
2338
2352
|
elementHandlers["Element.getOffset"] = async (ctx, params) => {
|
|
2339
2353
|
const ref = getElementRef(params);
|
|
2340
|
-
return
|
|
2341
|
-
${buildElAccess(ref)}
|
|
2354
|
+
return evalInElement(ctx, ref, `
|
|
2342
2355
|
if (!el) return { left: 0, top: 0 }
|
|
2343
2356
|
const r = el.getBoundingClientRect()
|
|
2344
2357
|
return { left: r.left, top: r.top }
|
|
2345
|
-
`)
|
|
2358
|
+
`);
|
|
2346
2359
|
};
|
|
2347
2360
|
elementHandlers["Element.getElement"] = async (ctx, params) => {
|
|
2348
2361
|
const parentRef = getElementRef(params);
|
|
2349
2362
|
const selector = params.selector;
|
|
2350
|
-
const
|
|
2351
|
-
const info = await evalInSim(ctx, inIframe(`
|
|
2352
|
-
${buildElAccess(parentRef, "parent")}
|
|
2363
|
+
const info = await evalInElement(ctx, parentRef, `
|
|
2353
2364
|
if (!parent) return null
|
|
2354
|
-
const child = parent.querySelector(
|
|
2365
|
+
const child = parent.querySelector(${JSON.stringify(selector)})
|
|
2355
2366
|
if (!child) return null
|
|
2356
2367
|
return { tagName: child.tagName.toLowerCase() }
|
|
2357
|
-
|
|
2368
|
+
`, "parent");
|
|
2358
2369
|
if (!info) throw new Error(`Child element not found: ${selector}`);
|
|
2359
2370
|
const combinedSelector = `${parentRef.selector} ${selector}`;
|
|
2360
2371
|
const elementId = registerElement(combinedSelector, 0, parentRef.pageId);
|
|
@@ -2363,14 +2374,12 @@ elementHandlers["Element.getElement"] = async (ctx, params) => {
|
|
|
2363
2374
|
elementHandlers["Element.getElements"] = async (ctx, params) => {
|
|
2364
2375
|
const parentRef = getElementRef(params);
|
|
2365
2376
|
const selector = params.selector;
|
|
2366
|
-
const
|
|
2367
|
-
const items = await evalInSim(ctx, inIframe(`
|
|
2368
|
-
${buildElAccess(parentRef, "parent")}
|
|
2377
|
+
const items = await evalInElement(ctx, parentRef, `
|
|
2369
2378
|
if (!parent) return []
|
|
2370
|
-
return Array.from(parent.querySelectorAll(
|
|
2379
|
+
return Array.from(parent.querySelectorAll(${JSON.stringify(selector)})).map(el => ({
|
|
2371
2380
|
tagName: el.tagName.toLowerCase(),
|
|
2372
2381
|
}))
|
|
2373
|
-
|
|
2382
|
+
`, "parent");
|
|
2374
2383
|
const combinedSelector = `${parentRef.selector} ${selector}`;
|
|
2375
2384
|
return {
|
|
2376
2385
|
elements: items.map((item, i) => ({
|
|
@@ -2556,7 +2565,7 @@ import CDP from "chrome-remote-interface";
|
|
|
2556
2565
|
var SIMULATOR_URL_PATTERN = "localhost:7788";
|
|
2557
2566
|
var MAX_BUFFER = 500;
|
|
2558
2567
|
var RECONNECT_INTERVAL_MS = 3e3;
|
|
2559
|
-
var cdpPort =
|
|
2568
|
+
var cdpPort = DEFAULT_CDP_PORT;
|
|
2560
2569
|
var targets = {
|
|
2561
2570
|
simulator: { client: null, connected: false, timer: null, consoleLogs: [], networkRequests: [] },
|
|
2562
2571
|
workbench: { client: null, connected: false, timer: null, consoleLogs: [], networkRequests: [] }
|
|
@@ -3174,16 +3183,20 @@ function startMcpServer(resolvedCdpPort, mcpPort) {
|
|
|
3174
3183
|
httpServer.on("error", (err) => {
|
|
3175
3184
|
if (err.code === "EADDRINUSE") {
|
|
3176
3185
|
console.warn(`[MCP] Port ${mcpPort} already in use \u2014 MCP server not started`);
|
|
3186
|
+
recordMcpFailed("port-in-use");
|
|
3177
3187
|
} else {
|
|
3178
3188
|
console.error("[MCP] Server error:", err);
|
|
3189
|
+
recordMcpFailed(err.message);
|
|
3179
3190
|
}
|
|
3180
3191
|
});
|
|
3181
3192
|
httpServer.listen(mcpPort, "127.0.0.1", () => {
|
|
3182
3193
|
console.log(`[MCP] SSE server listening on http://127.0.0.1:${mcpPort}/sse`);
|
|
3194
|
+
recordMcpStarted(mcpPort);
|
|
3183
3195
|
});
|
|
3184
3196
|
return toDisposable(() => {
|
|
3185
3197
|
transports.clear();
|
|
3186
3198
|
httpServer.close();
|
|
3199
|
+
recordMcpStopped();
|
|
3187
3200
|
});
|
|
3188
3201
|
}
|
|
3189
3202
|
|
|
@@ -3316,13 +3329,7 @@ function setupSimulatorStorage(host, options) {
|
|
|
3316
3329
|
}
|
|
3317
3330
|
return { securityOrigin: cachedOrigin, isLocalStorage: true };
|
|
3318
3331
|
}
|
|
3319
|
-
function
|
|
3320
|
-
if (host.isDestroyed()) return;
|
|
3321
|
-
const prefix = activePrefix();
|
|
3322
|
-
if (prefix && !evt.key.startsWith(prefix)) return;
|
|
3323
|
-
host.send(SimulatorStorageChannel.Event, evt);
|
|
3324
|
-
}
|
|
3325
|
-
async function setItem(key, value) {
|
|
3332
|
+
async function withStorageWrite(fn) {
|
|
3326
3333
|
await ensureAttached();
|
|
3327
3334
|
if (!attachedWc || attachedWc.isDestroyed()) {
|
|
3328
3335
|
return { ok: false, error: "simulator not attached" };
|
|
@@ -3330,92 +3337,74 @@ function setupSimulatorStorage(host, options) {
|
|
|
3330
3337
|
const storageId = await getStorageId();
|
|
3331
3338
|
if (!storageId) return { ok: false, error: "failed to resolve simulator origin" };
|
|
3332
3339
|
try {
|
|
3333
|
-
await attachedWc
|
|
3334
|
-
storageId,
|
|
3335
|
-
key,
|
|
3336
|
-
value
|
|
3337
|
-
});
|
|
3338
|
-
pushSyntheticEvent({ type: "added", key, newValue: value });
|
|
3339
|
-
return { ok: true };
|
|
3340
|
+
return await fn({ wc: attachedWc, storageId });
|
|
3340
3341
|
} catch (e) {
|
|
3341
3342
|
return { ok: false, error: e.message };
|
|
3342
3343
|
}
|
|
3343
3344
|
}
|
|
3344
|
-
async function
|
|
3345
|
+
async function withStorageRead(fallback, fn) {
|
|
3345
3346
|
await ensureAttached();
|
|
3346
|
-
if (!attachedWc || attachedWc.isDestroyed())
|
|
3347
|
-
return { ok: false, error: "simulator not attached" };
|
|
3348
|
-
}
|
|
3349
|
-
const storageId = await getStorageId();
|
|
3350
|
-
if (!storageId) return { ok: false, error: "failed to resolve simulator origin" };
|
|
3347
|
+
if (!attachedWc || attachedWc.isDestroyed()) return fallback;
|
|
3351
3348
|
try {
|
|
3352
|
-
await
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3349
|
+
const storageId = await getStorageId();
|
|
3350
|
+
if (!storageId) return fallback;
|
|
3351
|
+
return await fn({ wc: attachedWc, storageId });
|
|
3352
|
+
} catch {
|
|
3353
|
+
return fallback;
|
|
3354
|
+
}
|
|
3355
|
+
}
|
|
3356
|
+
function pushSyntheticEvent(evt) {
|
|
3357
|
+
if (host.isDestroyed()) return;
|
|
3358
|
+
const prefix = activePrefix();
|
|
3359
|
+
if (prefix && !evt.key.startsWith(prefix)) return;
|
|
3360
|
+
host.send(SimulatorStorageChannel.Event, evt);
|
|
3361
|
+
}
|
|
3362
|
+
async function setItem(key, value) {
|
|
3363
|
+
return withStorageWrite(async ({ wc, storageId }) => {
|
|
3364
|
+
await wc.debugger.sendCommand("DOMStorage.setDOMStorageItem", { storageId, key, value });
|
|
3365
|
+
pushSyntheticEvent({ type: "added", key, newValue: value });
|
|
3366
|
+
return { ok: true };
|
|
3367
|
+
});
|
|
3368
|
+
}
|
|
3369
|
+
async function removeItem(key) {
|
|
3370
|
+
return withStorageWrite(async ({ wc, storageId }) => {
|
|
3371
|
+
await wc.debugger.sendCommand("DOMStorage.removeDOMStorageItem", { storageId, key });
|
|
3356
3372
|
pushSyntheticEvent({ type: "removed", key });
|
|
3357
3373
|
return { ok: true };
|
|
3358
|
-
}
|
|
3359
|
-
return { ok: false, error: e.message };
|
|
3360
|
-
}
|
|
3374
|
+
});
|
|
3361
3375
|
}
|
|
3362
3376
|
async function clearScoped() {
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
return { ok: false, error: "simulator not attached" };
|
|
3366
|
-
}
|
|
3367
|
-
const storageId = await getStorageId();
|
|
3368
|
-
if (!storageId) return { ok: false, error: "failed to resolve simulator origin" };
|
|
3369
|
-
const prefix = activePrefix();
|
|
3370
|
-
try {
|
|
3377
|
+
return withStorageWrite(async ({ wc, storageId }) => {
|
|
3378
|
+
const prefix = activePrefix();
|
|
3371
3379
|
if (!prefix) {
|
|
3372
|
-
await
|
|
3380
|
+
await wc.debugger.sendCommand("DOMStorage.clear", { storageId });
|
|
3373
3381
|
return { ok: true };
|
|
3374
3382
|
}
|
|
3375
|
-
const result = await
|
|
3383
|
+
const result = await wc.debugger.sendCommand("DOMStorage.getDOMStorageItems", {
|
|
3376
3384
|
storageId
|
|
3377
3385
|
});
|
|
3378
3386
|
for (const [key] of result.entries) {
|
|
3379
3387
|
if (!key.startsWith(prefix)) continue;
|
|
3380
|
-
await
|
|
3381
|
-
storageId,
|
|
3382
|
-
key
|
|
3383
|
-
});
|
|
3388
|
+
await wc.debugger.sendCommand("DOMStorage.removeDOMStorageItem", { storageId, key });
|
|
3384
3389
|
}
|
|
3385
3390
|
return { ok: true };
|
|
3386
|
-
}
|
|
3387
|
-
return { ok: false, error: e.message };
|
|
3388
|
-
}
|
|
3391
|
+
});
|
|
3389
3392
|
}
|
|
3390
3393
|
async function clearAll() {
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
return { ok: false, error: "simulator not attached" };
|
|
3394
|
-
}
|
|
3395
|
-
const storageId = await getStorageId();
|
|
3396
|
-
if (!storageId) return { ok: false, error: "failed to resolve simulator origin" };
|
|
3397
|
-
try {
|
|
3398
|
-
await attachedWc.debugger.sendCommand("DOMStorage.clear", { storageId });
|
|
3394
|
+
return withStorageWrite(async ({ wc, storageId }) => {
|
|
3395
|
+
await wc.debugger.sendCommand("DOMStorage.clear", { storageId });
|
|
3399
3396
|
return { ok: true };
|
|
3400
|
-
}
|
|
3401
|
-
return { ok: false, error: e.message };
|
|
3402
|
-
}
|
|
3397
|
+
});
|
|
3403
3398
|
}
|
|
3404
3399
|
async function getSnapshot() {
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
try {
|
|
3408
|
-
const storageId = await getStorageId();
|
|
3409
|
-
if (!storageId) return [];
|
|
3410
|
-
const result = await attachedWc.debugger.sendCommand("DOMStorage.getDOMStorageItems", {
|
|
3400
|
+
return withStorageRead([], async ({ wc, storageId }) => {
|
|
3401
|
+
const result = await wc.debugger.sendCommand("DOMStorage.getDOMStorageItems", {
|
|
3411
3402
|
storageId
|
|
3412
3403
|
});
|
|
3413
3404
|
const prefix = activePrefix();
|
|
3414
3405
|
const filtered = prefix ? result.entries.filter(([key]) => key.startsWith(prefix)) : result.entries;
|
|
3415
3406
|
return filtered.map(([key, value]) => ({ key, value }));
|
|
3416
|
-
}
|
|
3417
|
-
return [];
|
|
3418
|
-
}
|
|
3407
|
+
});
|
|
3419
3408
|
}
|
|
3420
3409
|
for (const wc of wcStatic.getAllWebContents()) {
|
|
3421
3410
|
if (isSimulatorWebview(wc)) {
|
|
@@ -3729,7 +3718,7 @@ function enableDevRendererAutoReload(rendererDir2) {
|
|
|
3729
3718
|
const watcher = fs7.watch(rendererDir2, { recursive: true }, () => {
|
|
3730
3719
|
if (reloadTimer) clearTimeout(reloadTimer);
|
|
3731
3720
|
reloadTimer = setTimeout(() => {
|
|
3732
|
-
for (const win of
|
|
3721
|
+
for (const win of BrowserWindow4.getAllWindows()) {
|
|
3733
3722
|
win.webContents.reload();
|
|
3734
3723
|
}
|
|
3735
3724
|
}, 300);
|
|
@@ -3754,6 +3743,7 @@ function createWorkbenchApp(config = {}) {
|
|
|
3754
3743
|
const mainWindow = createConfiguredMainWindow(config, rendererDir2);
|
|
3755
3744
|
const context = createContext(config, mainWindow, rendererDir2);
|
|
3756
3745
|
context.registry.add(registerAppIpc(context));
|
|
3746
|
+
context.registry.add(installThemeBackgroundSync());
|
|
3757
3747
|
registerBuiltinModules(config, context);
|
|
3758
3748
|
installMenu(config, mainWindow, context);
|
|
3759
3749
|
const instance = {
|
|
@@ -3811,10 +3801,10 @@ function createWorkbenchApp(config = {}) {
|
|
|
3811
3801
|
}
|
|
3812
3802
|
|
|
3813
3803
|
// src/main/windows/settings-window/create.ts
|
|
3814
|
-
import { BrowserWindow as
|
|
3804
|
+
import { BrowserWindow as BrowserWindow5 } from "electron";
|
|
3815
3805
|
import path13 from "path";
|
|
3816
3806
|
async function createSettingsWindow(parent, rendererDir2) {
|
|
3817
|
-
const win = new
|
|
3807
|
+
const win = new BrowserWindow5({
|
|
3818
3808
|
width: 420,
|
|
3819
3809
|
height: 560,
|
|
3820
3810
|
minWidth: 380,
|
|
@@ -3846,18 +3836,17 @@ function launch(config = {}) {
|
|
|
3846
3836
|
return createWorkbenchApp(config).start();
|
|
3847
3837
|
}
|
|
3848
3838
|
async function openSettingsWindow(ctx) {
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
ctx.
|
|
3839
|
+
let win = ctx.windows.settingsWindow;
|
|
3840
|
+
if (!win || win.isDestroyed()) {
|
|
3841
|
+
win = await createSettingsWindow(ctx.windows.mainWindow, ctx.rendererDir);
|
|
3852
3842
|
ctx.windows.setSettingsWindow(win);
|
|
3853
3843
|
wireSettingsWindowEvents(win, () => {
|
|
3854
|
-
ctx.workbenchSettingsWindow = null;
|
|
3855
3844
|
ctx.windows.setSettingsWindow(null);
|
|
3856
3845
|
});
|
|
3857
3846
|
}
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
ctx.notify.workbenchSettingsInit(
|
|
3847
|
+
win.show();
|
|
3848
|
+
win.focus();
|
|
3849
|
+
ctx.notify.workbenchSettingsInit(win, {
|
|
3861
3850
|
settings: loadWorkbenchSettings()
|
|
3862
3851
|
});
|
|
3863
3852
|
}
|