@uxland/primary-shell 7.47.4 → 7.47.5
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/{component-CY-RSUBM.js → component-C6IdTseU.js} +2 -2
- package/dist/{component-CY-RSUBM.js.map → component-C6IdTseU.js.map} +1 -1
- package/dist/{index-BaVXV730.js → index-C2OnQp-I.js} +497 -457
- package/dist/index-C2OnQp-I.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/index.umd.cjs +2 -2
- package/dist/index.umd.cjs.map +1 -1
- package/dist/{plugin-DpQd-ZC5.js → plugin-C6qd-VVE.js} +2 -2
- package/dist/{plugin-DpQd-ZC5.js.map → plugin-C6qd-VVE.js.map} +1 -1
- package/dist/primary/shell/src/api/region-manager/region-manager.d.ts +3 -2
- package/dist/primary/shell/src/api/region-manager/remove-view-idempotency.test.d.ts +1 -0
- package/dist/primary/shell/src/features/exit/handler.d.ts +12 -0
- package/package.json +1 -1
- package/src/api/region-manager/region-manager.test.ts +57 -2
- package/src/api/region-manager/region-manager.ts +36 -4
- package/src/api/region-manager/remove-view-idempotency.test.ts +98 -0
- package/src/features/exit/handler.test.ts +60 -0
- package/src/features/exit/handler.ts +17 -1
- package/dist/index-BaVXV730.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { HarmonixRegionManager,
|
|
1
|
+
import { HarmonixRegionManager, HarmonixViewDefinition, IRegionManager } from '@uxland/harmonix';
|
|
2
2
|
import { PluginInfo } from '../../handle-plugins';
|
|
3
|
-
import { shellRegions, clinicalMonitoringRegions, activityHistoryRegions, administrativeManagementRegions } from './regions';
|
|
4
3
|
import { PrimariaBroker } from '../broker/primaria-broker';
|
|
4
|
+
import { activityHistoryRegions, administrativeManagementRegions, clinicalMonitoringRegions, shellRegions } from './regions';
|
|
5
5
|
export interface PrimariaRegionManager extends HarmonixRegionManager {
|
|
6
6
|
regions: {
|
|
7
7
|
shell: typeof shellRegions;
|
|
@@ -15,6 +15,7 @@ export interface PrimariaRegionManager extends HarmonixRegionManager {
|
|
|
15
15
|
activateMainView(viewId: string): Promise<void>;
|
|
16
16
|
activatePluginView(regionName: string, pluginId: string, viewId: string): Promise<void>;
|
|
17
17
|
getCurrentMainViewActive(): string | undefined;
|
|
18
|
+
_removeAllViews(): Promise<void>;
|
|
18
19
|
_destroy(): void;
|
|
19
20
|
}
|
|
20
21
|
/**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -4,6 +4,18 @@ export declare class ExitShellHandler {
|
|
|
4
4
|
private api;
|
|
5
5
|
constructor(api: PrimariaApi);
|
|
6
6
|
handle(exitEvent: ExitShell): Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* Desmunta les vistes de tots els plugins abans de fer-los el `dispose`.
|
|
9
|
+
*
|
|
10
|
+
* Els cleanups dels `useEffect` s'executen en desmuntar-se el component i poden enviar comandes
|
|
11
|
+
* pel broker (p. ex. `ClearTransportDetail` a petitioner). Si el `dispose` s'executa primer, el
|
|
12
|
+
* handler ja no hi és i el `send` rebutja. Cada plugin d'aquest repositori ja desmunta les seves
|
|
13
|
+
* vistes primer, però els de tercers no els controlem: fer-ho aquí els cobreix tots.
|
|
14
|
+
*
|
|
15
|
+
* Va dins del mateix `Promise.race` que el `dispose`, així que el límit de temps del tancament
|
|
16
|
+
* no canvia.
|
|
17
|
+
*/
|
|
18
|
+
private unmountViewsAndDisposePlugins;
|
|
7
19
|
private timeout;
|
|
8
20
|
private askForClose;
|
|
9
21
|
private emitClose;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @vitest-environment happy-dom
|
|
2
|
-
import {
|
|
3
|
-
import { createRegionManagerProxy } from "./region-manager";
|
|
2
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
4
3
|
import { BROKER_EVENTS } from "../broker/broker-events";
|
|
4
|
+
import { createRegionManagerProxy } from "./region-manager";
|
|
5
5
|
|
|
6
6
|
const pluginId = "test-plugin";
|
|
7
7
|
const mockView = { id: "view1", factory: () => Promise.resolve(document.createElement("div")) };
|
|
@@ -27,6 +27,7 @@ describe("RegionManagerProxy", () => {
|
|
|
27
27
|
registerViewWithRegion: vi.fn(),
|
|
28
28
|
unregisterViewFromRegion: vi.fn(),
|
|
29
29
|
getRegion: vi.fn().mockReturnValue(regionMock),
|
|
30
|
+
getRegisteredViews: vi.fn().mockReturnValue([]),
|
|
30
31
|
destroy: vi.fn(),
|
|
31
32
|
};
|
|
32
33
|
|
|
@@ -128,4 +129,58 @@ describe("RegionManagerProxy", () => {
|
|
|
128
129
|
proxy._destroy();
|
|
129
130
|
expect(regionManager.destroy).toHaveBeenCalled();
|
|
130
131
|
});
|
|
132
|
+
|
|
133
|
+
describe("_removeAllViews", () => {
|
|
134
|
+
/**
|
|
135
|
+
* Es crida en tancar, abans del `dispose` dels plugins, perque els cleanups dels `useEffect`
|
|
136
|
+
* trobin els handlers del broker encara registrats. Ha d'esperar cada desmuntatge: el
|
|
137
|
+
* `clear()`/`destroy()` del regionManager fan `forEach` amb crides asincrones sense
|
|
138
|
+
* esperar-les, i per aixo no serveixen.
|
|
139
|
+
*/
|
|
140
|
+
it("desregistra totes les vistes de totes les regions que tenen", async () => {
|
|
141
|
+
regionManager.getRegisteredViews = vi.fn((regionName: string) =>
|
|
142
|
+
regionName === "main-region"
|
|
143
|
+
? [
|
|
144
|
+
{ key: "a::v1", view: mockView },
|
|
145
|
+
{ key: "b::v2", view: mockView },
|
|
146
|
+
]
|
|
147
|
+
: [],
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
await proxy._removeAllViews();
|
|
151
|
+
|
|
152
|
+
expect(regionManager.unregisterViewFromRegion).toHaveBeenCalledWith("main-region", "a::v1");
|
|
153
|
+
expect(regionManager.unregisterViewFromRegion).toHaveBeenCalledWith("main-region", "b::v2");
|
|
154
|
+
expect(regionManager.unregisterViewFromRegion).toHaveBeenCalledTimes(2);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("espera cada desmuntatge abans de continuar amb el seguent", async () => {
|
|
158
|
+
const order: string[] = [];
|
|
159
|
+
regionManager.getRegisteredViews = vi.fn((regionName: string) =>
|
|
160
|
+
regionName === "main-region"
|
|
161
|
+
? [
|
|
162
|
+
{ key: "a::v1", view: mockView },
|
|
163
|
+
{ key: "b::v2", view: mockView },
|
|
164
|
+
]
|
|
165
|
+
: [],
|
|
166
|
+
);
|
|
167
|
+
regionManager.unregisterViewFromRegion = vi.fn(async (_region: string, key: string) => {
|
|
168
|
+
order.push(`start:${key}`);
|
|
169
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
170
|
+
order.push(`done:${key}`);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
await proxy._removeAllViews();
|
|
174
|
+
|
|
175
|
+
expect(order).toEqual(["start:a::v1", "done:a::v1", "start:b::v2", "done:b::v2"]);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it("no fa res si cap regio te vistes", async () => {
|
|
179
|
+
regionManager.getRegisteredViews = vi.fn().mockReturnValue([]);
|
|
180
|
+
|
|
181
|
+
await proxy._removeAllViews();
|
|
182
|
+
|
|
183
|
+
expect(regionManager.unregisterViewFromRegion).not.toHaveBeenCalled();
|
|
184
|
+
});
|
|
185
|
+
});
|
|
131
186
|
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { HarmonixRegionManager,
|
|
2
|
-
import { PluginInfo } from "../../handle-plugins";
|
|
1
|
+
import { HarmonixRegionManager, HarmonixViewDefinition, IRegionManager } from "@uxland/harmonix";
|
|
3
2
|
import { IRegion } from "@uxland/regions";
|
|
4
|
-
import {
|
|
5
|
-
import { PrimariaBroker } from "../broker/primaria-broker";
|
|
3
|
+
import { PluginInfo } from "../../handle-plugins";
|
|
6
4
|
import { BROKER_EVENTS } from "../broker/broker-events";
|
|
5
|
+
import { PrimariaBroker } from "../broker/primaria-broker";
|
|
6
|
+
import { activityHistoryRegions, administrativeManagementRegions, clinicalMonitoringRegions, shellRegions } from "./regions";
|
|
7
7
|
|
|
8
8
|
export interface PrimariaRegionManager extends HarmonixRegionManager {
|
|
9
9
|
regions: {
|
|
@@ -18,9 +18,18 @@ export interface PrimariaRegionManager extends HarmonixRegionManager {
|
|
|
18
18
|
activateMainView(viewId: string): Promise<void>;
|
|
19
19
|
activatePluginView(regionName: string, pluginId: string, viewId: string): Promise<void>;
|
|
20
20
|
getCurrentMainViewActive(): string | undefined;
|
|
21
|
+
_removeAllViews(): Promise<void>;
|
|
21
22
|
_destroy(): void;
|
|
22
23
|
}
|
|
23
24
|
|
|
25
|
+
/** Totes les regions que coneix el shell, per poder-les recórrer al tancar. */
|
|
26
|
+
const ALL_REGION_NAMES: string[] = [
|
|
27
|
+
...Object.values(shellRegions),
|
|
28
|
+
...Object.values(clinicalMonitoringRegions),
|
|
29
|
+
...Object.values(activityHistoryRegions),
|
|
30
|
+
...Object.values(administrativeManagementRegions),
|
|
31
|
+
];
|
|
32
|
+
|
|
24
33
|
class RegionManagerProxy implements PrimariaRegionManager {
|
|
25
34
|
regions = {
|
|
26
35
|
shell: shellRegions,
|
|
@@ -183,6 +192,29 @@ class RegionManagerProxy implements PrimariaRegionManager {
|
|
|
183
192
|
this.broker.publish(BROKER_EVENTS.shell.mainViewChanged, { viewId });
|
|
184
193
|
}
|
|
185
194
|
|
|
195
|
+
/**
|
|
196
|
+
* Desmunta totes les vistes de totes les regions, i espera que acabin.
|
|
197
|
+
*
|
|
198
|
+
* Es crida en tancar, ABANS de fer el `dispose` dels plugins: els cleanups dels `useEffect` que
|
|
199
|
+
* s'executen en desmuntar-se poden enviar comandes pel broker, i han de trobar el handler encara
|
|
200
|
+
* registrat. Cada plugin ja ho fa pel seu compte al `dispose`, però això només cobreix els
|
|
201
|
+
* plugins d'aquest repositori; els de tercers (econsulta, allergies…) no els controlem.
|
|
202
|
+
*
|
|
203
|
+
* Fa servir `unregisterViewFromRegion` i no `destroy()`/`clear()` del regionManager perquè
|
|
204
|
+
* aquests fan `forEach` amb crides asíncrones sense esperar-les, així que retornen abans que les
|
|
205
|
+
* vistes s'hagin desmuntat de debò.
|
|
206
|
+
*
|
|
207
|
+
* És idempotent: desregistrar una vista que ja no hi és no fa res.
|
|
208
|
+
*/
|
|
209
|
+
async _removeAllViews(): Promise<void> {
|
|
210
|
+
for (const regionName of ALL_REGION_NAMES) {
|
|
211
|
+
const registered = this.regionManager.getRegisteredViews(regionName) ?? [];
|
|
212
|
+
for (const { key } of [...registered]) {
|
|
213
|
+
await this.regionManager.unregisterViewFromRegion(regionName, key);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
186
218
|
_destroy() {
|
|
187
219
|
this.regionManager.destroy();
|
|
188
220
|
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
import { createRegionManager } from "@uxland/harmonix";
|
|
3
|
+
import { type IRegionAdapter, Region } from "@uxland/regions";
|
|
4
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Aquest test NO fa servir dobles del regionManager: munta una `Region` de `@uxland/regions` i un
|
|
8
|
+
* `RegionManager` de `@uxland/harmonix` de debo.
|
|
9
|
+
*
|
|
10
|
+
* El motiu: des que el shell desmunta totes les vistes al tancar (`_removeAllViews`), l'
|
|
11
|
+
* `unregisterViews` de cada plugin s'executa DESPRES, sobre vistes que ja no hi son. Tot el
|
|
12
|
+
* disseny es sosté en que aquesta segona passada sigui inofensiva, i aixo depen del comportament
|
|
13
|
+
* intern d'aquestes dues llibreries, no del nostre codi. Amb dobles no es provaria res.
|
|
14
|
+
*
|
|
15
|
+
* Si una actualitzacio d'aquests paquets fa que la segona crida arribi a l'adaptador, el
|
|
16
|
+
* component es desmuntaria dues vegades i ara mateix nomes ho sabriem en produccio.
|
|
17
|
+
*/
|
|
18
|
+
const REGION = "test-region";
|
|
19
|
+
const VIEW_KEY = "some-plugin::some-view";
|
|
20
|
+
|
|
21
|
+
let adapter: IRegionAdapter;
|
|
22
|
+
let regionManager: ReturnType<typeof createRegionManager>;
|
|
23
|
+
|
|
24
|
+
const createSpyAdapter = (): IRegionAdapter => ({
|
|
25
|
+
activateView: vi.fn().mockResolvedValue(undefined),
|
|
26
|
+
deactivateView: vi.fn().mockResolvedValue(undefined),
|
|
27
|
+
removeView: vi.fn(),
|
|
28
|
+
viewAdded: vi.fn().mockResolvedValue(undefined),
|
|
29
|
+
behaviors: [],
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const mountRegion = () => {
|
|
33
|
+
const host = document.createElement("div") as HTMLElement & { uxlRegion?: unknown };
|
|
34
|
+
const region = new Region(REGION, regionManager as never, host as never, adapter, {
|
|
35
|
+
name: REGION,
|
|
36
|
+
targetId: REGION,
|
|
37
|
+
});
|
|
38
|
+
regionManager.add(REGION, region);
|
|
39
|
+
return region;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const addAndActivateView = async (region: Region) => {
|
|
43
|
+
await regionManager.registerViewWithRegion(REGION, VIEW_KEY, {
|
|
44
|
+
factory: () => Promise.resolve(document.createElement("span")),
|
|
45
|
+
});
|
|
46
|
+
// Nomes les vistes actives tenen component, i `removeView` nomes crida l'adaptador si n'hi ha.
|
|
47
|
+
await region.activate(VIEW_KEY);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
beforeEach(() => {
|
|
51
|
+
adapter = createSpyAdapter();
|
|
52
|
+
regionManager = createRegionManager("test");
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
describe("treure una vista dues vegades (shell + plugin)", () => {
|
|
56
|
+
it("la primera passada desmunta la vista de debo", async () => {
|
|
57
|
+
const region = mountRegion();
|
|
58
|
+
await addAndActivateView(region);
|
|
59
|
+
|
|
60
|
+
await regionManager.unregisterViewFromRegion(REGION, VIEW_KEY);
|
|
61
|
+
|
|
62
|
+
expect(adapter.deactivateView).toHaveBeenCalledOnce();
|
|
63
|
+
expect(adapter.removeView).toHaveBeenCalledOnce();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("la segona no torna a tocar l'adaptador", async () => {
|
|
67
|
+
const region = mountRegion();
|
|
68
|
+
await addAndActivateView(region);
|
|
69
|
+
|
|
70
|
+
await regionManager.unregisterViewFromRegion(REGION, VIEW_KEY);
|
|
71
|
+
vi.mocked(adapter.deactivateView).mockClear();
|
|
72
|
+
vi.mocked(adapter.removeView).mockClear();
|
|
73
|
+
|
|
74
|
+
// El que fa `unregisterViews` del plugin despres que el shell ja ho hagi tret tot.
|
|
75
|
+
await regionManager.unregisterViewFromRegion(REGION, VIEW_KEY);
|
|
76
|
+
|
|
77
|
+
expect(adapter.deactivateView).not.toHaveBeenCalled();
|
|
78
|
+
expect(adapter.removeView).not.toHaveBeenCalled();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("la segona passada no llanca ni deixa la vista registrada", async () => {
|
|
82
|
+
const region = mountRegion();
|
|
83
|
+
await addAndActivateView(region);
|
|
84
|
+
|
|
85
|
+
await regionManager.unregisterViewFromRegion(REGION, VIEW_KEY);
|
|
86
|
+
|
|
87
|
+
await expect(regionManager.unregisterViewFromRegion(REGION, VIEW_KEY)).resolves.toBeDefined();
|
|
88
|
+
expect(region.containsView(VIEW_KEY)).toBe(false);
|
|
89
|
+
expect(regionManager.getRegisteredViews(REGION)).toEqual([]);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("treure una vista que no s'ha registrat mai tampoc fa res", async () => {
|
|
93
|
+
mountRegion();
|
|
94
|
+
|
|
95
|
+
await expect(regionManager.unregisterViewFromRegion(REGION, "mai::registrada")).resolves.toBeDefined();
|
|
96
|
+
expect(adapter.removeView).not.toHaveBeenCalled();
|
|
97
|
+
});
|
|
98
|
+
});
|
|
@@ -30,6 +30,9 @@ const createMockApi = (): PrimariaApi =>
|
|
|
30
30
|
notificationService: {
|
|
31
31
|
error: vi.fn(),
|
|
32
32
|
},
|
|
33
|
+
regionManager: {
|
|
34
|
+
_removeAllViews: vi.fn().mockResolvedValue(undefined),
|
|
35
|
+
},
|
|
33
36
|
}) as any;
|
|
34
37
|
|
|
35
38
|
describe("ExitShellHandler", () => {
|
|
@@ -180,4 +183,61 @@ describe("ExitShellHandler", () => {
|
|
|
180
183
|
expect(mockApi.interactionService.confirm).not.toHaveBeenCalled();
|
|
181
184
|
});
|
|
182
185
|
});
|
|
186
|
+
|
|
187
|
+
describe("ordre de tancament: vistes abans que plugins", () => {
|
|
188
|
+
/**
|
|
189
|
+
* Els cleanups dels `useEffect` s'executen en desmuntar-se el component i poden enviar
|
|
190
|
+
* comandes pel broker (p. ex. `ClearTransportDetail` a petitioner). Si el `dispose` dels
|
|
191
|
+
* plugins corre primer, el handler ja no hi es i el `send` rebutja. Cada plugin d'aquest
|
|
192
|
+
* repositori ja ho ordena be, pero els de tercers no els controlem: aquest ordre els cobreix.
|
|
193
|
+
*/
|
|
194
|
+
it("desmunta totes les vistes abans de disposar els plugins", async () => {
|
|
195
|
+
const order: string[] = [];
|
|
196
|
+
(mockApi.regionManager._removeAllViews as any).mockImplementation(async () => {
|
|
197
|
+
order.push("removeAllViews");
|
|
198
|
+
});
|
|
199
|
+
(disposePlugins as any).mockImplementation(async () => {
|
|
200
|
+
order.push("disposePlugins");
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
await handler.handle({} as ExitShell);
|
|
204
|
+
|
|
205
|
+
expect(order).toEqual(["removeAllViews", "disposePlugins"]);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it("no comenca a disposar fins que el desmuntatge ha acabat", async () => {
|
|
209
|
+
let finishUnmount: () => void = () => {};
|
|
210
|
+
(mockApi.regionManager._removeAllViews as any).mockImplementation(
|
|
211
|
+
() =>
|
|
212
|
+
new Promise<void>((resolve) => {
|
|
213
|
+
finishUnmount = resolve;
|
|
214
|
+
}),
|
|
215
|
+
);
|
|
216
|
+
(disposePlugins as any).mockResolvedValue(undefined);
|
|
217
|
+
|
|
218
|
+
const handled = handler.handle({} as ExitShell);
|
|
219
|
+
await Promise.resolve();
|
|
220
|
+
await Promise.resolve();
|
|
221
|
+
expect(disposePlugins).not.toHaveBeenCalled();
|
|
222
|
+
|
|
223
|
+
finishUnmount();
|
|
224
|
+
await handled;
|
|
225
|
+
|
|
226
|
+
expect(disposePlugins).toHaveBeenCalled();
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it("el limit de temps del tancament segueix cobrint tot el proces", async () => {
|
|
230
|
+
vi.useFakeTimers();
|
|
231
|
+
(mockApi.regionManager._removeAllViews as any).mockImplementation(() => new Promise<void>(() => {}));
|
|
232
|
+
|
|
233
|
+
const handled = handler.handle({} as ExitShell);
|
|
234
|
+
await vi.advanceTimersByTimeAsync(10000);
|
|
235
|
+
await handled;
|
|
236
|
+
|
|
237
|
+
// Encara que el desmuntatge no acabi mai, el tancament continua.
|
|
238
|
+
expect(disposeShell).toHaveBeenCalled();
|
|
239
|
+
expect(raiseCloseEvent).toHaveBeenCalled();
|
|
240
|
+
vi.useRealTimers();
|
|
241
|
+
});
|
|
242
|
+
});
|
|
183
243
|
});
|
|
@@ -27,7 +27,7 @@ export class ExitShellHandler {
|
|
|
27
27
|
|
|
28
28
|
// Per si un plugin tarda molt en fer dispose, màxim deixarem 5 segons, per no interrompre el tancar infinitament
|
|
29
29
|
await Promise.race([
|
|
30
|
-
|
|
30
|
+
this.unmountViewsAndDisposePlugins(), // S'intenta executar un dispose normal
|
|
31
31
|
this.timeout(10000), // Si passen 5s, es segueix amb l'execució
|
|
32
32
|
]);
|
|
33
33
|
disposeShell();
|
|
@@ -38,6 +38,22 @@ export class ExitShellHandler {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Desmunta les vistes de tots els plugins abans de fer-los el `dispose`.
|
|
43
|
+
*
|
|
44
|
+
* Els cleanups dels `useEffect` s'executen en desmuntar-se el component i poden enviar comandes
|
|
45
|
+
* pel broker (p. ex. `ClearTransportDetail` a petitioner). Si el `dispose` s'executa primer, el
|
|
46
|
+
* handler ja no hi és i el `send` rebutja. Cada plugin d'aquest repositori ja desmunta les seves
|
|
47
|
+
* vistes primer, però els de tercers no els controlem: fer-ho aquí els cobreix tots.
|
|
48
|
+
*
|
|
49
|
+
* Va dins del mateix `Promise.race` que el `dispose`, així que el límit de temps del tancament
|
|
50
|
+
* no canvia.
|
|
51
|
+
*/
|
|
52
|
+
private async unmountViewsAndDisposePlugins(): Promise<void> {
|
|
53
|
+
await this.api.regionManager._removeAllViews();
|
|
54
|
+
await disposePlugins();
|
|
55
|
+
}
|
|
56
|
+
|
|
41
57
|
private timeout(ms: number) {
|
|
42
58
|
return new Promise<void>((resolve) => setTimeout(resolve, ms));
|
|
43
59
|
}
|