@dimina-kit/devtools 0.4.0-dev.20260701083540 → 0.4.0-dev.20260702145840
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/main/app/app.js +11 -0
- package/dist/main/app/max-listeners-diagnostic.d.ts +32 -0
- package/dist/main/app/max-listeners-diagnostic.js +63 -0
- package/dist/main/index.bundle.js +1657 -1158
- package/dist/main/ipc/bridge-router.d.ts +33 -4
- package/dist/main/ipc/bridge-router.js +200 -51
- package/dist/main/ipc/session-listener-bag.d.ts +41 -0
- package/dist/main/ipc/session-listener-bag.js +40 -0
- package/dist/main/ipc/simulator.js +5 -5
- package/dist/main/ipc/views.js +8 -19
- package/dist/main/services/automation/wait-active-page.d.ts +4 -2
- package/dist/main/services/elements-forward/index.js +19 -0
- package/dist/main/services/network-forward/index.js +13 -0
- package/dist/main/services/render-inspect/index.d.ts +9 -0
- package/dist/main/services/render-inspect/index.js +13 -1
- package/dist/main/services/simulator-storage/index.d.ts +9 -0
- package/dist/main/services/simulator-storage/index.js +26 -1
- package/dist/main/services/simulator-wxml/index.js +117 -11
- package/dist/main/services/views/apply-view-ops.d.ts +11 -0
- package/dist/main/services/views/apply-view-ops.js +22 -0
- package/dist/main/services/views/destroy-child-view.d.ts +9 -0
- package/dist/main/services/views/destroy-child-view.js +23 -0
- package/dist/main/services/views/host-toolbar-view.d.ts +21 -0
- package/dist/main/services/views/host-toolbar-view.js +249 -0
- package/dist/main/services/views/inject-when-ready.d.ts +41 -0
- package/dist/main/services/views/inject-when-ready.js +62 -0
- package/dist/main/services/views/native-simulator-devtools-host.d.ts +26 -0
- package/dist/main/services/views/native-simulator-devtools-host.js +484 -0
- package/dist/main/services/views/native-simulator-view.d.ts +28 -0
- package/dist/main/services/views/native-simulator-view.js +428 -0
- package/dist/main/services/views/overlay-panels-view.d.ts +29 -0
- package/dist/main/services/views/overlay-panels-view.js +150 -0
- package/dist/main/services/views/placement-reconciler.d.ts +73 -0
- package/dist/main/services/views/placement-reconciler.js +120 -0
- package/dist/main/services/views/placement-test-driver.d.ts +25 -0
- package/dist/main/services/views/placement-test-driver.js +48 -0
- package/dist/main/services/views/resolve-project-editor-target.d.ts +13 -0
- package/dist/main/services/views/resolve-project-editor-target.js +33 -0
- package/dist/main/services/views/view-manager.d.ts +28 -70
- package/dist/main/services/views/view-manager.js +66 -1514
- package/dist/main/services/views/workbench-view.d.ts +15 -0
- package/dist/main/services/views/workbench-view.js +170 -0
- package/dist/main/services/workbench-context.d.ts +10 -0
- package/dist/preload/windows/host-toolbar-runtime.cjs +6 -13
- package/dist/preload/windows/host-toolbar-runtime.cjs.map +2 -2
- package/dist/preload/windows/main.cjs +10 -1
- package/dist/preload/windows/main.cjs.map +2 -2
- package/dist/preload/windows/simulator.cjs +6 -3
- package/dist/preload/windows/simulator.cjs.map +2 -2
- package/dist/preload/windows/simulator.js +6 -3
- package/dist/render-host/render-inspect.js +35 -1
- package/dist/renderer/assets/index-ChF9V4r-.js +49 -0
- package/dist/renderer/assets/{input-DR7bfyQE.js → input-Cjk0wSEh.js} +2 -2
- package/dist/renderer/assets/ipc-transport-D5dKIti1.css +1 -0
- package/dist/renderer/assets/{ipc-transport-3Arg8jPC.js → ipc-transport-OZS-KmOW.js} +2 -2
- package/dist/renderer/assets/{popover-CPZX3MrT.js → popover-CQVvOe90.js} +2 -2
- package/dist/renderer/assets/{select-BxyPlVyJ.js → select-BQDXi5ih.js} +2 -2
- package/dist/renderer/assets/{settings-api-CtPPJF-F.js → settings-api-B6x2mhaD.js} +2 -2
- package/dist/renderer/assets/{settings-CG_OR03F.js → settings-tP3Px2KR.js} +2 -2
- package/dist/renderer/assets/{workbenchSettings-ClqCBGOa.js → workbenchSettings-Bim9ol9R.js} +2 -2
- package/dist/renderer/entries/main/index.html +6 -6
- package/dist/renderer/entries/popover/index.html +5 -5
- package/dist/renderer/entries/settings/index.html +5 -5
- package/dist/renderer/entries/workbench-settings/index.html +4 -4
- package/dist/service-host/sync-api-patch.js +33 -3
- package/dist/shared/bridge-channels.d.ts +17 -0
- package/dist/shared/bridge-channels.js +9 -0
- package/dist/shared/ipc-channels.d.ts +29 -14
- package/dist/shared/ipc-channels.js +16 -17
- package/dist/shared/ipc-schemas.d.ts +25 -17
- package/dist/shared/ipc-schemas.js +38 -22
- package/dist/shared/view-ids.d.ts +19 -0
- package/dist/shared/view-ids.js +25 -0
- package/dist/simulator/assets/{bridge-channels-BUQ5AbvJ.js → bridge-channels-zhsumfky.js} +2 -2
- package/dist/simulator/assets/{device-shell-CT3LRnTB.js → device-shell-CUl0ILfn.js} +2 -2
- package/dist/simulator/assets/{simulator-BizhGGE3.js → simulator-Dz8iGcgy.js} +5 -5
- package/dist/simulator/assets/{simulator-mini-app-BfNuDF3R.js → simulator-mini-app-Bt639XL_.js} +2 -2
- package/dist/simulator/simulator.html +2 -1
- package/package.json +4 -4
- package/dist/renderer/assets/index-HE9Xr9bQ.js +0 -49
- package/dist/renderer/assets/ipc-transport-Dt0jR7Ir.css +0 -1
|
@@ -22,9 +22,11 @@
|
|
|
22
22
|
* - Resolve exactly once; later events are inert and the subscription is torn
|
|
23
23
|
* down on resolve.
|
|
24
24
|
*/
|
|
25
|
-
/** The render-event shape `waitForActivePage` reads (subset of `RenderEvent`).
|
|
25
|
+
/** The render-event shape `waitForActivePage` reads (subset of `RenderEvent`).
|
|
26
|
+
* Only `activePage` events end the wait; other kinds (`domReady`/`domMutated`)
|
|
27
|
+
* are inert but included so a full `RenderEvent` is assignable here. */
|
|
26
28
|
export interface ActivePageEventLike {
|
|
27
|
-
kind: 'domReady' | 'activePage';
|
|
29
|
+
kind: 'domReady' | 'activePage' | 'domMutated';
|
|
28
30
|
appId: string;
|
|
29
31
|
bridgeId: string;
|
|
30
32
|
pagePath?: string;
|
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
* hook + dispatch scripts) as self-contained code.
|
|
50
50
|
*/
|
|
51
51
|
import { webContents as electronWebContents } from 'electron';
|
|
52
|
+
import { isFrontendSettled } from '../views/inject-when-ready.js';
|
|
52
53
|
/**
|
|
53
54
|
* CDP domains that target the RENDER GUEST'S document tree. A command in one of
|
|
54
55
|
* these is intercepted and sent to the active render guest's debugger instead of
|
|
@@ -274,6 +275,12 @@ export function installElementsForward(deps) {
|
|
|
274
275
|
function dispatchToFrontend(message) {
|
|
275
276
|
if (disposed || devtoolsWc.isDestroyed())
|
|
276
277
|
return;
|
|
278
|
+
// Unified settled gate (same predicate as the reconcile tick): an unsettled
|
|
279
|
+
// front-end wipes its state on load anyway, so the message is meaningless
|
|
280
|
+
// there — and the executeJavaScript would queue one did-stop-loading waiter
|
|
281
|
+
// per push (an activePage burst piles them). The post-settle tick re-primes.
|
|
282
|
+
if (!isFrontendSettled(devtoolsWc))
|
|
283
|
+
return;
|
|
277
284
|
let json;
|
|
278
285
|
try {
|
|
279
286
|
json = JSON.stringify(message);
|
|
@@ -309,6 +316,10 @@ export function installElementsForward(deps) {
|
|
|
309
316
|
function pushDocumentUpdated() {
|
|
310
317
|
if (disposed || devtoolsWc.isDestroyed())
|
|
311
318
|
return;
|
|
319
|
+
// Same unified settled gate as dispatchToFrontend — render events (the
|
|
320
|
+
// activePage burst) drive this during churn.
|
|
321
|
+
if (!isFrontendSettled(devtoolsWc))
|
|
322
|
+
return;
|
|
312
323
|
let script;
|
|
313
324
|
try {
|
|
314
325
|
script = buildDocumentUpdatedScript();
|
|
@@ -594,6 +605,14 @@ export function installElementsForward(deps) {
|
|
|
594
605
|
stop();
|
|
595
606
|
return;
|
|
596
607
|
}
|
|
608
|
+
// An unsettled front-end can't run the script anyway, and executeJavaScript
|
|
609
|
+
// against it queues one did-stop-loading waiter PER TICK on the emitter
|
|
610
|
+
// (150ms × a seconds-long reload piles past the MaxListeners ceiling).
|
|
611
|
+
// MUST be the shared Electron-aligned predicate — a bare isLoading()
|
|
612
|
+
// probe diverges from Electron's internal isLoadingMainFrame gate and
|
|
613
|
+
// keeps piling. Skip; the first post-settle tick re-establishes the hook.
|
|
614
|
+
if (!isFrontendSettled(devtoolsWc))
|
|
615
|
+
return;
|
|
597
616
|
devtoolsWc
|
|
598
617
|
.executeJavaScript(buildReconcileScript())
|
|
599
618
|
.then((res) => {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DisposableRegistry, toDisposable } from '@dimina-kit/electron-deck/main';
|
|
2
|
+
import { isFrontendSettled } from '../views/inject-when-ready.js';
|
|
2
3
|
// ── requestId namespacing (pure, testable) ──────────────────────────────────
|
|
3
4
|
/**
|
|
4
5
|
* CDP events whose `params.requestId` we rewrite into the virtual namespace.
|
|
@@ -359,6 +360,18 @@ export function createNetworkForwarder(bridge) {
|
|
|
359
360
|
trimQueue();
|
|
360
361
|
return;
|
|
361
362
|
}
|
|
363
|
+
if (!isFrontendSettled(wc)) {
|
|
364
|
+
// An unsettled front-end can't run the dispatch script anyway — and every
|
|
365
|
+
// executeJavaScript against it queues one did-stop-loading waiter on the
|
|
366
|
+
// emitter, so a relaunch's network burst piles them past the MaxListeners
|
|
367
|
+
// ceiling. MUST be the shared Electron-aligned predicate (a bare
|
|
368
|
+
// isLoading() probe diverges from the internal isLoadingMainFrame gate).
|
|
369
|
+
// Hold the (bounded) queue; the next event's flush or the ready-retry
|
|
370
|
+
// delivers after the load.
|
|
371
|
+
trimQueue();
|
|
372
|
+
scheduleReadyRetry();
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
362
375
|
if (sink === 'idle')
|
|
363
376
|
beginProbing();
|
|
364
377
|
// Pack greedily up to MAX_BATCH_CHARS so one executeJavaScript stays sized;
|
|
@@ -24,6 +24,15 @@ export interface RenderInspector {
|
|
|
24
24
|
highlight(wc: WebContents, sid: string): Promise<ElementInspection | null>;
|
|
25
25
|
/** Clear any highlight overlay in the guest. */
|
|
26
26
|
unhighlight(wc: WebContents): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Toggle the guest-side WXML MutationObserver. When on, the injected IIFE
|
|
29
|
+
* watches `document.body` and posts a debounced `wxmlChanged` over
|
|
30
|
+
* `DiminaRenderBridge` on every DOM mutation (setData), which bridge-router
|
|
31
|
+
* turns into a `domMutated` render event so the WXML panel re-pulls. Only
|
|
32
|
+
* enabled while the WXML panel is visible, so an unseen panel never drives a
|
|
33
|
+
* full Vue-tree walk. Injects the IIFE first if needed; no-op on a dead guest.
|
|
34
|
+
*/
|
|
35
|
+
setWxmlObserving(wc: WebContents, on: boolean): Promise<void>;
|
|
27
36
|
}
|
|
28
37
|
export interface RenderInspectorOptions {
|
|
29
38
|
/** Override the injected IIFE source (default: read the built bundle). Test seam. */
|
|
@@ -259,6 +259,18 @@ export function createRenderInspector(options = {}) {
|
|
|
259
259
|
// best-effort
|
|
260
260
|
}
|
|
261
261
|
}
|
|
262
|
-
|
|
262
|
+
async function setWxmlObserving(wc, on) {
|
|
263
|
+
if (wc.isDestroyed())
|
|
264
|
+
return;
|
|
265
|
+
if (!(await ensureInjected(wc)))
|
|
266
|
+
return;
|
|
267
|
+
try {
|
|
268
|
+
await wc.executeJavaScript(`window.__diminaRenderInspect && window.__diminaRenderInspect.setWxmlObserving(${on ? 'true' : 'false'})`);
|
|
269
|
+
}
|
|
270
|
+
catch {
|
|
271
|
+
// best-effort: a guest mid-teardown just stops observing on its own.
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return { getWxml, highlight, unhighlight, setWxmlObserving };
|
|
263
275
|
}
|
|
264
276
|
//# sourceMappingURL=index.js.map
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { type WebContents } from 'electron';
|
|
17
17
|
import { type ConnectionRegistry, type Disposable } from '@dimina-kit/electron-deck/main';
|
|
18
|
+
import { type SyncStorageChange } from '../../../shared/ipc-channels.js';
|
|
18
19
|
import { type SenderPolicy } from '../../utils/ipc-registry.js';
|
|
19
20
|
import type { BridgeRouterHandle } from '../../ipc/bridge-router.js';
|
|
20
21
|
import type { RenderInspector } from '../render-inspect/index.js';
|
|
@@ -34,6 +35,14 @@ export declare const STORAGE_API_NAMES: Set<string>;
|
|
|
34
35
|
export interface SimulatorStorageHandle extends Disposable {
|
|
35
36
|
/** Present only under native-host; wired to ctx.storageApi for bridge-router. */
|
|
36
37
|
storageApi: StorageApi | null;
|
|
38
|
+
/**
|
|
39
|
+
* Native-host SYNC-storage liveness: bridge-router calls this on each
|
|
40
|
+
* `storageChanged` container message the service-host posts after a
|
|
41
|
+
* `setStorageSync`/`removeStorageSync`/`clearStorageSync`. Those write the
|
|
42
|
+
* service-host `localStorage` directly (bypassing main), so they'd otherwise
|
|
43
|
+
* leave the panel stale until reload — this pushes the matching `StorageEvent`.
|
|
44
|
+
*/
|
|
45
|
+
onSyncStorageChange(appId: string, change: SyncStorageChange): void;
|
|
37
46
|
}
|
|
38
47
|
export interface SimulatorStorageOptions {
|
|
39
48
|
/**
|
|
@@ -573,7 +573,32 @@ export function setupSimulatorStorage(host, options) {
|
|
|
573
573
|
const storageApi = options.bridge?.isNativeHost()
|
|
574
574
|
? { invoke: runtimeInvoke }
|
|
575
575
|
: null;
|
|
576
|
-
|
|
576
|
+
/**
|
|
577
|
+
* SYNC wx storage APIs run inside the service-host window and write
|
|
578
|
+
* `localStorage` directly, so they never reach `setItem`/`runtimeInvoke` here.
|
|
579
|
+
* The service-host posts the change over `DiminaServiceBridge` and bridge-router
|
|
580
|
+
* routes it here so the panel stays live. Only the ACTIVE app's changes are
|
|
581
|
+
* surfaced (the panel shows one app); the key already carries the `${appId}_`
|
|
582
|
+
* prefix, matching the CDP / async event shape.
|
|
583
|
+
*/
|
|
584
|
+
function onSyncStorageChange(appId, change) {
|
|
585
|
+
if (appId !== getActiveAppId())
|
|
586
|
+
return;
|
|
587
|
+
if (host.isDestroyed())
|
|
588
|
+
return;
|
|
589
|
+
switch (change.op) {
|
|
590
|
+
case 'set':
|
|
591
|
+
pushSyntheticEvent({ type: 'added', key: change.key, newValue: change.value });
|
|
592
|
+
break;
|
|
593
|
+
case 'remove':
|
|
594
|
+
pushSyntheticEvent({ type: 'removed', key: change.key });
|
|
595
|
+
break;
|
|
596
|
+
case 'clear':
|
|
597
|
+
host.send(SimulatorStorageChannel.Event, { type: 'cleared' });
|
|
598
|
+
break;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
return { dispose: () => registry.dispose(), storageApi, onSyncStorageChange };
|
|
577
602
|
}
|
|
578
603
|
// Element inspection delegates to the simulator preload's __simulatorData
|
|
579
604
|
// bridge via executeJavaScript. Looked up independently from `attachedWc` so
|
|
@@ -4,25 +4,131 @@ import { IpcRegistry } from '../../utils/ipc-registry.js';
|
|
|
4
4
|
export function setupSimulatorWxml(host, options) {
|
|
5
5
|
const { bridge, inspector, getActiveAppId } = options;
|
|
6
6
|
const registry = new DisposableRegistry();
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
// Whether the WXML panel is currently visible (renderer drives this via
|
|
8
|
+
// SetActive). Live tree pushes + the render-guest DOM observer only run while
|
|
9
|
+
// active, so an unseen panel never triggers a full Vue-tree walk.
|
|
10
|
+
let active = false;
|
|
11
|
+
// latest-wins: only the newest pull's result is pushed (a slow walk that
|
|
12
|
+
// resolves after a newer one must not clobber the fresher tree).
|
|
13
|
+
let seq = 0;
|
|
14
|
+
// in-flight coalescing: at most one pull runs at a time; a request that lands
|
|
15
|
+
// mid-pull sets `again` so exactly one follow-up pull runs after it settles.
|
|
16
|
+
let pulling = false;
|
|
17
|
+
let again = false;
|
|
18
|
+
// The render guest currently being observed, so we can stop it on page change
|
|
19
|
+
// / deactivation (single owner).
|
|
20
|
+
let observedWc = null;
|
|
21
|
+
/** The visible page's render WebContents of the active app, or null. */
|
|
22
|
+
function activeWc() {
|
|
23
|
+
return bridge.getActiveRenderWc(getActiveAppId() ?? undefined);
|
|
24
|
+
}
|
|
25
|
+
/** Read the WXML tree of a render guest, or null when there is none. */
|
|
26
|
+
async function pull(wc) {
|
|
10
27
|
if (!wc)
|
|
11
28
|
return null;
|
|
12
29
|
return inspector.getWxml(wc);
|
|
13
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Pull the active tree and push it, gated by `active` and reconciled by
|
|
33
|
+
* latest-wins + in-flight coalescing so a burst of render events (setData)
|
|
34
|
+
* collapses to a single fresh push instead of a pile of overlapping walks.
|
|
35
|
+
*/
|
|
36
|
+
function schedulePull() {
|
|
37
|
+
if (!active)
|
|
38
|
+
return;
|
|
39
|
+
const mySeq = ++seq;
|
|
40
|
+
if (pulling) {
|
|
41
|
+
again = true;
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
pulling = true;
|
|
45
|
+
void pull(activeWc())
|
|
46
|
+
.then((tree) => {
|
|
47
|
+
// Re-check `active` at send time: a pull started while visible must NOT
|
|
48
|
+
// push after the panel was hidden / disposed (deactivate bumps `seq`, so
|
|
49
|
+
// `mySeq === seq` also guards, but the explicit `active` check is the
|
|
50
|
+
// clear invariant).
|
|
51
|
+
if (mySeq === seq && active && !host.isDestroyed()) {
|
|
52
|
+
host.send(SimulatorWxmlChannel.Event, tree);
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
.finally(() => {
|
|
56
|
+
pulling = false;
|
|
57
|
+
if (again) {
|
|
58
|
+
again = false;
|
|
59
|
+
schedulePull();
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
function startObserving(wc) {
|
|
64
|
+
if (!wc)
|
|
65
|
+
return;
|
|
66
|
+
observedWc = wc;
|
|
67
|
+
// The guest IIFE defers observe() until document.body exists, so a wc whose
|
|
68
|
+
// DOM isn't up yet still starts observing once it loads — no retry needed here.
|
|
69
|
+
void inspector.setWxmlObserving(wc, true);
|
|
70
|
+
}
|
|
71
|
+
function stopObserving() {
|
|
72
|
+
const wc = observedWc;
|
|
73
|
+
observedWc = null;
|
|
74
|
+
if (wc)
|
|
75
|
+
void inspector.setWxmlObserving(wc, false);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Point the DOM observer at the CURRENT active render guest. Called on every
|
|
79
|
+
* render event while active, so the observer installs even when SetActive fired
|
|
80
|
+
* before the guest existed (the guest appears on `domReady`) and follows the
|
|
81
|
+
* active page across navigation (`activePage`).
|
|
82
|
+
*/
|
|
83
|
+
function reconcileObserving() {
|
|
84
|
+
if (!active)
|
|
85
|
+
return;
|
|
86
|
+
const wc = activeWc();
|
|
87
|
+
if (wc !== observedWc) {
|
|
88
|
+
stopObserving();
|
|
89
|
+
startObserving(wc);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/** Invalidate any in-flight pull + queued re-pull so nothing pushes post-hide. */
|
|
93
|
+
function cancelPending() {
|
|
94
|
+
seq++;
|
|
95
|
+
again = false;
|
|
96
|
+
}
|
|
14
97
|
const ipc = new IpcRegistry(options.senderPolicy);
|
|
15
|
-
ipc.handle(SimulatorWxmlChannel.GetSnapshot, () => pull());
|
|
98
|
+
ipc.handle(SimulatorWxmlChannel.GetSnapshot, () => pull(activeWc()));
|
|
99
|
+
ipc.handle(SimulatorWxmlChannel.SetActive, (_event, on) => {
|
|
100
|
+
if (on) {
|
|
101
|
+
active = true;
|
|
102
|
+
reconcileObserving();
|
|
103
|
+
schedulePull(); // seed the now-visible panel
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
active = false;
|
|
107
|
+
cancelPending();
|
|
108
|
+
stopObserving();
|
|
109
|
+
}
|
|
110
|
+
});
|
|
16
111
|
registry.add(ipc);
|
|
17
|
-
// Re-read + push
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
112
|
+
// Re-read + push on render-side activity: a page's DOM mounted (`domReady`),
|
|
113
|
+
// the visible page changed (`activePage`), or the active page's DOM mutated in
|
|
114
|
+
// place (`domMutated`, from the render-guest observer). Gated by `active` and
|
|
115
|
+
// scoped to the ACTIVE app so a background app's / stale bridge's event never
|
|
116
|
+
// drives a spurious full walk of the visible page.
|
|
117
|
+
const unsubscribe = bridge.onRenderEvent((event) => {
|
|
118
|
+
if (!active)
|
|
119
|
+
return;
|
|
120
|
+
const appId = getActiveAppId();
|
|
121
|
+
if (appId && event.appId !== appId)
|
|
122
|
+
return;
|
|
123
|
+
// domReady: the guest may have just appeared → (re)install the observer.
|
|
124
|
+
// activePage: the active guest changed → move the observer.
|
|
125
|
+
// domMutated: same guest → reconcile is a no-op, then pull.
|
|
126
|
+
reconcileObserving();
|
|
127
|
+
schedulePull();
|
|
24
128
|
});
|
|
25
129
|
registry.add(unsubscribe);
|
|
130
|
+
// Stop observing + invalidate in-flight pulls on teardown (best-effort).
|
|
131
|
+
registry.add(() => { active = false; cancelPending(); stopObserving(); });
|
|
26
132
|
return registry;
|
|
27
133
|
}
|
|
28
134
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Bounds, ViewOp } from '@dimina-kit/electron-deck/layout';
|
|
2
|
+
import type { DevtoolsExtra } from '../../../shared/view-ids.js';
|
|
3
|
+
export interface ViewOpTarget {
|
|
4
|
+
attach(viewId: string): void;
|
|
5
|
+
detach(viewId: string): void;
|
|
6
|
+
setBounds(viewId: string, bounds: Bounds, extra?: DevtoolsExtra): void;
|
|
7
|
+
setVisible(viewId: string, visible: boolean): void;
|
|
8
|
+
reorder(order: string[]): void;
|
|
9
|
+
}
|
|
10
|
+
export declare function applyViewOps(ops: ViewOp<DevtoolsExtra>[], target: ViewOpTarget): void;
|
|
11
|
+
//# sourceMappingURL=apply-view-ops.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function applyViewOps(ops, target) {
|
|
2
|
+
for (const op of ops) {
|
|
3
|
+
switch (op.kind) {
|
|
4
|
+
case 'detach':
|
|
5
|
+
target.detach(op.viewId);
|
|
6
|
+
break;
|
|
7
|
+
case 'setVisible':
|
|
8
|
+
target.setVisible(op.viewId, op.visible);
|
|
9
|
+
break;
|
|
10
|
+
case 'setBounds':
|
|
11
|
+
target.setBounds(op.viewId, op.bounds, op.extra);
|
|
12
|
+
break;
|
|
13
|
+
case 'attach':
|
|
14
|
+
target.attach(op.viewId);
|
|
15
|
+
break;
|
|
16
|
+
case 'reorder':
|
|
17
|
+
target.reorder(op.order);
|
|
18
|
+
break;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=apply-view-ops.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { BrowserWindow, WebContentsView } from 'electron';
|
|
2
|
+
/**
|
|
3
|
+
* Detach a child overlay WebContentsView from the main window's contentView and
|
|
4
|
+
* close its webContents. Tolerates an already-removed view and a destroyed
|
|
5
|
+
* webContents (best-effort teardown). The single low-level view-destroy path
|
|
6
|
+
* shared by every overlay domain.
|
|
7
|
+
*/
|
|
8
|
+
export declare function destroyChildView(mainWindow: BrowserWindow, view: WebContentsView | null): void;
|
|
9
|
+
//# sourceMappingURL=destroy-child-view.d.ts.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detach a child overlay WebContentsView from the main window's contentView and
|
|
3
|
+
* close its webContents. Tolerates an already-removed view and a destroyed
|
|
4
|
+
* webContents (best-effort teardown). The single low-level view-destroy path
|
|
5
|
+
* shared by every overlay domain.
|
|
6
|
+
*/
|
|
7
|
+
export function destroyChildView(mainWindow, view) {
|
|
8
|
+
if (!view)
|
|
9
|
+
return;
|
|
10
|
+
if (!mainWindow.isDestroyed()) {
|
|
11
|
+
try {
|
|
12
|
+
mainWindow.contentView.removeChildView(view);
|
|
13
|
+
}
|
|
14
|
+
catch { /* already removed */ }
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
if (!view.webContents.isDestroyed()) {
|
|
18
|
+
view.webContents.close();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
catch { /* ignore */ }
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=destroy-child-view.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { PlacementReconciler } from './placement-reconciler.js';
|
|
2
|
+
import type { HostToolbarControl, ViewManagerContext } from './view-manager.js';
|
|
3
|
+
/**
|
|
4
|
+
* A strip above the devtools header that the downstream host loads its own
|
|
5
|
+
* content into and fully controls. Bounds come from a renderer DOM anchor
|
|
6
|
+
* (forward anchor, like the simulator DevTools overlay); its height is dynamic
|
|
7
|
+
* via a reverse size-advertiser the toolbar's own renderer drives.
|
|
8
|
+
*/
|
|
9
|
+
export interface HostToolbarView {
|
|
10
|
+
readonly control: HostToolbarControl;
|
|
11
|
+
setHostToolbarHeight(extent: number): void;
|
|
12
|
+
getHostToolbarHeight(): number;
|
|
13
|
+
getHostToolbarWebContentsId(): number | null;
|
|
14
|
+
/** Teardown for `disposeAll`: sweep the port, destroy the view, release the runtime ref. */
|
|
15
|
+
dispose(): void;
|
|
16
|
+
}
|
|
17
|
+
export declare function createHostToolbarView(ctx: ViewManagerContext, reconciler: PlacementReconciler, deps: {
|
|
18
|
+
/** Re-apply the settings/popover overlays whose height depends on the toolbar strip. */
|
|
19
|
+
reapplyPresentOverlays(): void;
|
|
20
|
+
}): HostToolbarView;
|
|
21
|
+
//# sourceMappingURL=host-toolbar-view.d.ts.map
|