1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 | Object.defineProperty(exports, "__esModule", { value: true });
|
18 | exports.FrontendApplication = void 0;
|
19 | const tslib_1 = require("tslib");
|
20 | const inversify_1 = require("inversify");
|
21 | const common_1 = require("../common");
|
22 | const keybinding_1 = require("./keybinding");
|
23 | const widgets_1 = require("./widgets");
|
24 | const application_shell_1 = require("./shell/application-shell");
|
25 | const shell_layout_restorer_1 = require("./shell/shell-layout-restorer");
|
26 | const frontend_application_state_1 = require("./frontend-application-state");
|
27 | const browser_1 = require("./browser");
|
28 | const core_preferences_1 = require("./core-preferences");
|
29 | const window_service_1 = require("./window/window-service");
|
30 | const tooltip_service_1 = require("./tooltip-service");
|
31 | const frontend_application_contribution_1 = require("./frontend-application-contribution");
|
32 | const TIMER_WARNING_THRESHOLD = 100;
|
33 | let FrontendApplication = class FrontendApplication {
|
34 | constructor(commands, menus, keybindings, layoutRestorer, contributions, _shell, stateService) {
|
35 | this.commands = commands;
|
36 | this.menus = menus;
|
37 | this.keybindings = keybindings;
|
38 | this.layoutRestorer = layoutRestorer;
|
39 | this.contributions = contributions;
|
40 | this._shell = _shell;
|
41 | this.stateService = stateService;
|
42 | }
|
43 | get shell() {
|
44 | return this._shell;
|
45 | }
|
46 | |
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 | async start() {
|
56 | const startup = this.backendStopwatch.start('frontend');
|
57 | await this.measure('startContributions', () => this.startContributions(), 'Start frontend contributions', false);
|
58 | this.stateService.state = 'started_contributions';
|
59 | const host = await this.getHost();
|
60 | this.attachShell(host);
|
61 | this.attachTooltip(host);
|
62 | await (0, browser_1.animationFrame)();
|
63 | this.stateService.state = 'attached_shell';
|
64 | await this.measure('initializeLayout', () => this.initializeLayout(), 'Initialize the workbench layout', false);
|
65 | this.stateService.state = 'initialized_layout';
|
66 | await this.fireOnDidInitializeLayout();
|
67 | await this.measure('revealShell', () => this.revealShell(host), 'Replace loading indicator with ready workbench UI (animation)', false);
|
68 | this.registerEventListeners();
|
69 | this.stateService.state = 'ready';
|
70 | startup.then(idToken => this.backendStopwatch.stop(idToken, 'Frontend application start', []));
|
71 | }
|
72 | |
73 |
|
74 |
|
75 | getHost() {
|
76 | if (document.body) {
|
77 | return Promise.resolve(document.body);
|
78 | }
|
79 | return new Promise(resolve => window.addEventListener('load', () => resolve(document.body), { once: true }));
|
80 | }
|
81 | |
82 |
|
83 |
|
84 | getStartupIndicator(host) {
|
85 | const startupElements = host.getElementsByClassName('theia-preload');
|
86 | return startupElements.length === 0 ? undefined : startupElements[0];
|
87 | }
|
88 | |
89 |
|
90 |
|
91 | registerEventListeners() {
|
92 | this.windowsService.onUnload(() => {
|
93 | this.stateService.state = 'closing_window';
|
94 | this.layoutRestorer.storeLayout(this);
|
95 | this.stopContributions();
|
96 | });
|
97 | window.addEventListener('resize', () => this.shell.update());
|
98 | this.keybindings.registerEventListeners(window);
|
99 | document.addEventListener('touchmove', event => { event.preventDefault(); }, { passive: false });
|
100 |
|
101 | if (common_1.isOSX) {
|
102 | document.body.addEventListener('wheel', browser_1.preventNavigation, { passive: false });
|
103 | }
|
104 |
|
105 | document.addEventListener('dragenter', event => {
|
106 | if (event.dataTransfer) {
|
107 | event.dataTransfer.dropEffect = 'none';
|
108 | }
|
109 | event.preventDefault();
|
110 | }, false);
|
111 | document.addEventListener('dragover', event => {
|
112 | if (event.dataTransfer) {
|
113 | event.dataTransfer.dropEffect = 'none';
|
114 | }
|
115 | event.preventDefault();
|
116 | }, false);
|
117 | document.addEventListener('drop', event => {
|
118 | event.preventDefault();
|
119 | }, false);
|
120 | }
|
121 | |
122 |
|
123 |
|
124 |
|
125 | attachShell(host) {
|
126 | const ref = this.getStartupIndicator(host);
|
127 | widgets_1.Widget.attach(this.shell, host, ref);
|
128 | }
|
129 | |
130 |
|
131 |
|
132 | attachTooltip(host) {
|
133 | this.tooltipService.attachTo(host);
|
134 | }
|
135 | |
136 |
|
137 |
|
138 |
|
139 | revealShell(host) {
|
140 | const startupElem = this.getStartupIndicator(host);
|
141 | if (startupElem) {
|
142 | return new Promise(resolve => {
|
143 | window.requestAnimationFrame(() => {
|
144 | startupElem.classList.add('theia-hidden');
|
145 | const preloadStyle = window.getComputedStyle(startupElem);
|
146 | const transitionDuration = (0, browser_1.parseCssTime)(preloadStyle.transitionDuration, 0);
|
147 | window.setTimeout(() => {
|
148 | const parent = startupElem.parentElement;
|
149 | if (parent) {
|
150 | parent.removeChild(startupElem);
|
151 | }
|
152 | resolve();
|
153 | }, transitionDuration);
|
154 | });
|
155 | });
|
156 | }
|
157 | else {
|
158 | return Promise.resolve();
|
159 | }
|
160 | }
|
161 | |
162 |
|
163 |
|
164 |
|
165 | async initializeLayout() {
|
166 | if (!await this.restoreLayout()) {
|
167 |
|
168 | await this.createDefaultLayout();
|
169 | }
|
170 | await this.shell.pendingUpdates;
|
171 | }
|
172 | |
173 |
|
174 |
|
175 | async restoreLayout() {
|
176 | try {
|
177 | return await this.layoutRestorer.restoreLayout(this);
|
178 | }
|
179 | catch (error) {
|
180 | if (shell_layout_restorer_1.ApplicationShellLayoutMigrationError.is(error)) {
|
181 | console.warn(error.message);
|
182 | console.info('Initializing the default layout instead...');
|
183 | }
|
184 | else {
|
185 | console.error('Could not restore layout', error);
|
186 | }
|
187 | return false;
|
188 | }
|
189 | }
|
190 | |
191 |
|
192 |
|
193 |
|
194 | async createDefaultLayout() {
|
195 | for (const contribution of this.contributions.getContributions()) {
|
196 | if (contribution.initializeLayout) {
|
197 | await this.measure(contribution.constructor.name + '.initializeLayout', () => contribution.initializeLayout(this));
|
198 | }
|
199 | }
|
200 | }
|
201 | async fireOnDidInitializeLayout() {
|
202 | for (const contribution of this.contributions.getContributions()) {
|
203 | if (contribution.onDidInitializeLayout) {
|
204 | await this.measure(contribution.constructor.name + '.onDidInitializeLayout', () => contribution.onDidInitializeLayout(this));
|
205 | }
|
206 | }
|
207 | }
|
208 | |
209 |
|
210 |
|
211 | async startContributions() {
|
212 | for (const contribution of this.contributions.getContributions()) {
|
213 | if (contribution.initialize) {
|
214 | try {
|
215 | await this.measure(contribution.constructor.name + '.initialize', () => contribution.initialize());
|
216 | }
|
217 | catch (error) {
|
218 | console.error('Could not initialize contribution', error);
|
219 | }
|
220 | }
|
221 | }
|
222 | for (const contribution of this.contributions.getContributions()) {
|
223 | if (contribution.configure) {
|
224 | try {
|
225 | await this.measure(contribution.constructor.name + '.configure', () => contribution.configure(this));
|
226 | }
|
227 | catch (error) {
|
228 | console.error('Could not configure contribution', error);
|
229 | }
|
230 | }
|
231 | }
|
232 | |
233 |
|
234 |
|
235 |
|
236 |
|
237 | await this.measure('commands.onStart', () => this.commands.onStart());
|
238 | await this.measure('keybindings.onStart', () => this.keybindings.onStart());
|
239 | await this.measure('menus.onStart', () => this.menus.onStart());
|
240 | for (const contribution of this.contributions.getContributions()) {
|
241 | if (contribution.onStart) {
|
242 | try {
|
243 | await this.measure(contribution.constructor.name + '.onStart', () => contribution.onStart(this));
|
244 | }
|
245 | catch (error) {
|
246 | console.error('Could not start contribution', error);
|
247 | }
|
248 | }
|
249 | }
|
250 | }
|
251 | |
252 |
|
253 |
|
254 | stopContributions() {
|
255 | console.info('>>> Stopping frontend contributions...');
|
256 | for (const contribution of this.contributions.getContributions()) {
|
257 | if (contribution.onStop) {
|
258 | try {
|
259 | contribution.onStop(this);
|
260 | }
|
261 | catch (error) {
|
262 | console.error('Could not stop contribution', error);
|
263 | }
|
264 | }
|
265 | }
|
266 | console.info('<<< All frontend contributions have been stopped.');
|
267 | }
|
268 | async measure(name, fn, message = `Frontend ${name}`, threshold = true) {
|
269 | return this.stopwatch.startAsync(name, message, fn, threshold ? { thresholdMillis: TIMER_WARNING_THRESHOLD, defaultLogLevel: common_1.LogLevel.DEBUG } : {});
|
270 | }
|
271 | };
|
272 | (0, tslib_1.__decorate)([
|
273 | (0, inversify_1.inject)(core_preferences_1.CorePreferences),
|
274 | (0, tslib_1.__metadata)("design:type", Object)
|
275 | ], FrontendApplication.prototype, "corePreferences", void 0);
|
276 | (0, tslib_1.__decorate)([
|
277 | (0, inversify_1.inject)(window_service_1.WindowService),
|
278 | (0, tslib_1.__metadata)("design:type", Object)
|
279 | ], FrontendApplication.prototype, "windowsService", void 0);
|
280 | (0, tslib_1.__decorate)([
|
281 | (0, inversify_1.inject)(tooltip_service_1.TooltipService),
|
282 | (0, tslib_1.__metadata)("design:type", Object)
|
283 | ], FrontendApplication.prototype, "tooltipService", void 0);
|
284 | (0, tslib_1.__decorate)([
|
285 | (0, inversify_1.inject)(common_1.Stopwatch),
|
286 | (0, tslib_1.__metadata)("design:type", common_1.Stopwatch)
|
287 | ], FrontendApplication.prototype, "stopwatch", void 0);
|
288 | (0, tslib_1.__decorate)([
|
289 | (0, inversify_1.inject)(common_1.BackendStopwatch),
|
290 | (0, tslib_1.__metadata)("design:type", Object)
|
291 | ], FrontendApplication.prototype, "backendStopwatch", void 0);
|
292 | FrontendApplication = (0, tslib_1.__decorate)([
|
293 | (0, inversify_1.injectable)(),
|
294 | (0, tslib_1.__param)(0, (0, inversify_1.inject)(common_1.CommandRegistry)),
|
295 | (0, tslib_1.__param)(1, (0, inversify_1.inject)(common_1.MenuModelRegistry)),
|
296 | (0, tslib_1.__param)(2, (0, inversify_1.inject)(keybinding_1.KeybindingRegistry)),
|
297 | (0, tslib_1.__param)(3, (0, inversify_1.inject)(shell_layout_restorer_1.ShellLayoutRestorer)),
|
298 | (0, tslib_1.__param)(4, (0, inversify_1.inject)(common_1.ContributionProvider)),
|
299 | (0, tslib_1.__param)(4, (0, inversify_1.named)(frontend_application_contribution_1.FrontendApplicationContribution)),
|
300 | (0, tslib_1.__param)(5, (0, inversify_1.inject)(application_shell_1.ApplicationShell)),
|
301 | (0, tslib_1.__param)(6, (0, inversify_1.inject)(frontend_application_state_1.FrontendApplicationStateService)),
|
302 | (0, tslib_1.__metadata)("design:paramtypes", [common_1.CommandRegistry,
|
303 | common_1.MenuModelRegistry,
|
304 | keybinding_1.KeybindingRegistry,
|
305 | shell_layout_restorer_1.ShellLayoutRestorer, Object, application_shell_1.ApplicationShell,
|
306 | frontend_application_state_1.FrontendApplicationStateService])
|
307 | ], FrontendApplication);
|
308 | exports.FrontendApplication = FrontendApplication;
|
309 |
|
\ | No newline at end of file |