@theia/core 1.37.0-next.8 → 1.37.0
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 +7 -9
- package/i18n/nls.cs.json +6 -1
- package/i18n/nls.de.json +6 -1
- package/i18n/nls.es.json +6 -1
- package/i18n/nls.fr.json +6 -1
- package/i18n/nls.hu.json +6 -1
- package/i18n/nls.it.json +6 -1
- package/i18n/nls.ja.json +6 -1
- package/i18n/nls.json +6 -1
- package/i18n/nls.pl.json +6 -1
- package/i18n/nls.pt-br.json +6 -1
- package/i18n/nls.pt-pt.json +6 -1
- package/i18n/nls.ru.json +6 -1
- package/i18n/nls.zh-cn.json +6 -1
- package/lib/browser/core-preferences.d.ts +4 -0
- package/lib/browser/core-preferences.d.ts.map +1 -1
- package/lib/browser/core-preferences.js +22 -0
- package/lib/browser/core-preferences.js.map +1 -1
- package/lib/browser/hover-service.d.ts +5 -0
- package/lib/browser/hover-service.d.ts.map +1 -1
- package/lib/browser/hover-service.js +7 -1
- package/lib/browser/hover-service.js.map +1 -1
- package/lib/browser/icon-theme-service.js +1 -1
- package/lib/browser/icon-theme-service.js.map +1 -1
- package/lib/browser/shell/application-shell.d.ts +2 -1
- package/lib/browser/shell/application-shell.d.ts.map +1 -1
- package/lib/browser/shell/application-shell.js +30 -3
- package/lib/browser/shell/application-shell.js.map +1 -1
- package/lib/browser/shell/tab-bars.d.ts +21 -5
- package/lib/browser/shell/tab-bars.d.ts.map +1 -1
- package/lib/browser/shell/tab-bars.js +94 -17
- package/lib/browser/shell/tab-bars.js.map +1 -1
- package/lib/browser/test/jsdom.js +1 -1
- package/lib/browser/test/jsdom.js.map +1 -1
- package/lib/browser/tree/tree-iterator.js +4 -4
- package/lib/browser/tree/tree-iterator.js.map +1 -1
- package/lib/browser/tree/tree-selection-state.spec.js +26 -2
- package/lib/browser/tree/tree-selection-state.spec.js.map +1 -1
- package/lib/common/i18n/localization.d.ts +1 -0
- package/lib/common/i18n/localization.d.ts.map +1 -1
- package/lib/common/i18n/localization.js +2 -16
- package/lib/common/i18n/localization.js.map +1 -1
- package/lib/common/nls.d.ts +1 -0
- package/lib/common/nls.d.ts.map +1 -1
- package/lib/common/nls.js +2 -1
- package/lib/common/nls.js.map +1 -1
- package/lib/common/quick-pick-service.d.ts +2 -1
- package/lib/common/quick-pick-service.d.ts.map +1 -1
- package/lib/common/quick-pick-service.js.map +1 -1
- package/lib/electron-browser/electron-clipboard-service.d.ts.map +1 -1
- package/lib/electron-browser/electron-clipboard-service.js +2 -3
- package/lib/electron-browser/electron-clipboard-service.js.map +1 -1
- package/lib/electron-browser/keyboard/electron-keyboard-layout-change-notifier.d.ts.map +1 -1
- package/lib/electron-browser/keyboard/electron-keyboard-layout-change-notifier.js +1 -2
- package/lib/electron-browser/keyboard/electron-keyboard-layout-change-notifier.js.map +1 -1
- package/lib/electron-browser/menu/electron-context-menu-renderer.d.ts +2 -3
- package/lib/electron-browser/menu/electron-context-menu-renderer.d.ts.map +1 -1
- package/lib/electron-browser/menu/electron-context-menu-renderer.js +10 -18
- package/lib/electron-browser/menu/electron-context-menu-renderer.js.map +1 -1
- package/lib/electron-browser/menu/electron-main-menu-factory.d.ts +10 -8
- package/lib/electron-browser/menu/electron-main-menu-factory.d.ts.map +1 -1
- package/lib/electron-browser/menu/electron-main-menu-factory.js +33 -32
- package/lib/electron-browser/menu/electron-main-menu-factory.js.map +1 -1
- package/lib/electron-browser/menu/electron-menu-contribution.d.ts +6 -6
- package/lib/electron-browser/menu/electron-menu-contribution.d.ts.map +1 -1
- package/lib/electron-browser/menu/electron-menu-contribution.js +39 -54
- package/lib/electron-browser/menu/electron-menu-contribution.js.map +1 -1
- package/lib/electron-browser/messaging/electron-ipc-connection-provider.d.ts.map +1 -1
- package/lib/electron-browser/messaging/electron-ipc-connection-provider.js +2 -6
- package/lib/electron-browser/messaging/electron-ipc-connection-provider.js.map +1 -1
- package/lib/electron-browser/preload.d.ts +2 -0
- package/lib/electron-browser/preload.d.ts.map +1 -0
- package/lib/electron-browser/preload.js +183 -0
- package/lib/electron-browser/preload.js.map +1 -0
- package/lib/electron-browser/token/electron-token-frontend-module.d.ts.map +1 -1
- package/lib/electron-browser/token/electron-token-frontend-module.js +1 -2
- package/lib/electron-browser/token/electron-token-frontend-module.js.map +1 -1
- package/lib/electron-browser/window/electron-frontend-application-state.d.ts.map +1 -1
- package/lib/electron-browser/window/electron-frontend-application-state.js +1 -3
- package/lib/electron-browser/window/electron-frontend-application-state.js.map +1 -1
- package/lib/electron-browser/window/electron-secondary-window-service.d.ts +1 -3
- package/lib/electron-browser/window/electron-secondary-window-service.d.ts.map +1 -1
- package/lib/electron-browser/window/electron-secondary-window-service.js +6 -34
- package/lib/electron-browser/window/electron-secondary-window-service.js.map +1 -1
- package/lib/electron-browser/window/electron-window-service.d.ts +1 -8
- package/lib/electron-browser/window/electron-window-service.d.ts.map +1 -1
- package/lib/electron-browser/window/electron-window-service.js +8 -25
- package/lib/electron-browser/window/electron-window-service.js.map +1 -1
- package/lib/electron-common/electron-api.d.ts +94 -0
- package/lib/electron-common/electron-api.d.ts.map +1 -0
- package/lib/electron-common/electron-api.js +53 -0
- package/lib/electron-common/electron-api.js.map +1 -0
- package/lib/electron-common/messaging/electron-connection-handler.d.ts +0 -7
- package/lib/electron-common/messaging/electron-connection-handler.d.ts.map +1 -1
- package/lib/electron-common/messaging/electron-connection-handler.js +1 -5
- package/lib/electron-common/messaging/electron-connection-handler.js.map +1 -1
- package/lib/electron-main/electron-api-main.d.ts +21 -0
- package/lib/electron-main/electron-api-main.d.ts.map +1 -0
- package/lib/electron-main/electron-api-main.js +261 -0
- package/lib/electron-main/electron-api-main.js.map +1 -0
- package/lib/electron-main/electron-main-application-module.d.ts.map +1 -1
- package/lib/electron-main/electron-main-application-module.js +3 -3
- package/lib/electron-main/electron-main-application-module.js.map +1 -1
- package/lib/electron-main/electron-main-application.d.ts +8 -2
- package/lib/electron-main/electron-main-application.d.ts.map +1 -1
- package/lib/electron-main/electron-main-application.js +32 -29
- package/lib/electron-main/electron-main-application.js.map +1 -1
- package/lib/electron-main/electron-security-token-service.d.ts.map +1 -1
- package/lib/electron-main/electron-security-token-service.js +2 -1
- package/lib/electron-main/electron-security-token-service.js.map +1 -1
- package/lib/electron-main/messaging/electron-messaging-contribution.d.ts +4 -5
- package/lib/electron-main/messaging/electron-messaging-contribution.d.ts.map +1 -1
- package/lib/electron-main/messaging/electron-messaging-contribution.js +4 -7
- package/lib/electron-main/messaging/electron-messaging-contribution.js.map +1 -1
- package/lib/electron-main/theia-electron-window.d.ts +2 -4
- package/lib/electron-main/theia-electron-window.d.ts.map +1 -1
- package/lib/electron-main/theia-electron-window.js +11 -34
- package/lib/electron-main/theia-electron-window.js.map +1 -1
- package/lib/node/i18n/localization-backend-contribution.d.ts.map +1 -1
- package/lib/node/i18n/localization-backend-contribution.js +2 -1
- package/lib/node/i18n/localization-backend-contribution.js.map +1 -1
- package/lib/node/i18n/localization-provider.d.ts.map +1 -1
- package/lib/node/i18n/localization-provider.js +2 -1
- package/lib/node/i18n/localization-provider.js.map +1 -1
- package/package.json +9 -6
- package/src/browser/core-preferences.ts +26 -0
- package/src/browser/hover-service.ts +12 -1
- package/src/browser/icon-theme-service.ts +1 -1
- package/src/browser/shell/application-shell.ts +29 -1
- package/src/browser/shell/tab-bars.ts +111 -17
- package/src/browser/style/hover-service.css +4 -0
- package/src/browser/style/tabs.css +25 -0
- package/src/browser/style/tree.css +1 -0
- package/src/browser/test/jsdom.ts +1 -1
- package/src/browser/tree/tree-iterator.ts +4 -4
- package/src/browser/tree/tree-selection-state.spec.ts +29 -2
- package/src/common/i18n/localization.ts +6 -16
- package/src/common/nls.ts +3 -1
- package/src/common/quick-pick-service.ts +2 -1
- package/src/electron-browser/electron-clipboard-service.ts +2 -3
- package/src/electron-browser/keyboard/electron-keyboard-layout-change-notifier.ts +1 -2
- package/src/electron-browser/menu/electron-context-menu-renderer.ts +10 -17
- package/src/electron-browser/menu/electron-main-menu-factory.ts +51 -44
- package/src/electron-browser/menu/electron-menu-contribution.ts +46 -57
- package/src/electron-browser/messaging/electron-ipc-connection-provider.ts +4 -9
- package/src/electron-browser/preload.ts +208 -0
- package/src/electron-browser/token/electron-token-frontend-module.ts +1 -2
- package/src/electron-browser/window/electron-frontend-application-state.ts +1 -3
- package/src/electron-browser/window/electron-secondary-window-service.ts +7 -31
- package/src/electron-browser/window/electron-window-service.ts +8 -25
- package/src/electron-common/electron-api.ts +134 -0
- package/src/electron-common/messaging/electron-connection-handler.ts +0 -9
- package/src/electron-main/electron-api-main.ts +291 -0
- package/src/electron-main/electron-main-application-module.ts +3 -4
- package/src/electron-main/electron-main-application.ts +33 -37
- package/src/electron-main/electron-security-token-service.ts +2 -1
- package/src/electron-main/messaging/electron-messaging-contribution.ts +8 -10
- package/src/electron-main/theia-electron-window.ts +8 -33
- package/src/node/i18n/localization-backend-contribution.ts +2 -1
- package/src/node/i18n/localization-provider.ts +2 -1
- package/LICENSE +0 -642
- package/electron-shared/@electron/remote/index.d.ts +0 -1
- package/electron-shared/@electron/remote/index.js +0 -1
- package/electron-shared/@electron/remote/main/index.d.ts +0 -1
- package/electron-shared/@electron/remote/main/index.js +0 -1
- package/lib/electron-common/messaging/electron-messages.d.ts +0 -25
- package/lib/electron-common/messaging/electron-messages.d.ts.map +0 -1
- package/lib/electron-common/messaging/electron-messages.js +0 -37
- package/lib/electron-common/messaging/electron-messages.js.map +0 -1
- package/lib/electron-main/electron-native-keymap.d.ts +0 -8
- package/lib/electron-main/electron-native-keymap.d.ts.map +0 -1
- package/lib/electron-main/electron-native-keymap.js +0 -48
- package/lib/electron-main/electron-native-keymap.js.map +0 -1
- package/src/electron-common/messaging/electron-messages.ts +0 -42
- package/src/electron-main/electron-native-keymap.ts +0 -40
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2023 STMicroelectronics and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
ipcMain, BrowserWindow, Menu, MenuItemConstructorOptions, webContents, WebContents, session, shell, clipboard, IpcMainEvent
|
|
19
|
+
} from '@theia/electron/shared/electron';
|
|
20
|
+
import * as nativeKeymap from '@theia/electron/shared/native-keymap';
|
|
21
|
+
|
|
22
|
+
import { inject, injectable } from 'inversify';
|
|
23
|
+
import { FrontendApplicationState, StopReason } from '../common/frontend-application-state';
|
|
24
|
+
import { ElectronSecurityToken } from '../electron-common/electron-token';
|
|
25
|
+
import {
|
|
26
|
+
CHANNEL_GET_SECURITY_TOKEN, CHANNEL_SET_MENU, MenuDto, CHANNEL_INVOKE_MENU, CHANNEL_FOCUS_WINDOW,
|
|
27
|
+
CHANNEL_ATTACH_SECURITY_TOKEN, CHANNEL_OPEN_POPUP, CHANNEL_ON_CLOSE_POPUP, CHANNEL_CLOSE_POPUP,
|
|
28
|
+
CHANNEL_GET_TITLE_STYLE_AT_STARTUP,
|
|
29
|
+
CHANNEL_MINIMIZE,
|
|
30
|
+
CHANNEL_MAXIMIZE,
|
|
31
|
+
CHANNEL_UNMAXIMIZE,
|
|
32
|
+
CHANNEL_CLOSE,
|
|
33
|
+
CHANNEL_ON_WINDOW_EVENT,
|
|
34
|
+
WindowEvent,
|
|
35
|
+
CHANNEL_TOGGLE_DEVTOOLS,
|
|
36
|
+
CHANNEL_SET_ZOOM_LEVEL,
|
|
37
|
+
CHANNEL_GET_ZOOM_LEVEL,
|
|
38
|
+
CHANNEL_IS_FULL_SCREENABLE,
|
|
39
|
+
CHANNEL_REQUEST_CLOSE,
|
|
40
|
+
CHANNEL_RESTART,
|
|
41
|
+
CHANNEL_SET_TITLE_STYLE,
|
|
42
|
+
CHANNEL_REQUEST_RELOAD,
|
|
43
|
+
CHANNEL_APP_STATE_CHANGED,
|
|
44
|
+
CHANNEL_SHOW_ITEM_IN_FOLDER,
|
|
45
|
+
CHANNEL_READ_CLIPBOARD,
|
|
46
|
+
CHANNEL_WRITE_CLIPBOARD,
|
|
47
|
+
CHANNEL_IPC_CONNECTION,
|
|
48
|
+
CHANNEL_IS_FULL_SCREEN,
|
|
49
|
+
InternalMenuDto,
|
|
50
|
+
CHANNEL_SET_MENU_BAR_VISIBLE,
|
|
51
|
+
CHANNEL_TOGGLE_FULL_SCREEN,
|
|
52
|
+
CHANNEL_IS_MAXIMIZED
|
|
53
|
+
} from '../electron-common/electron-api';
|
|
54
|
+
import { ElectronMainApplication, ElectronMainApplicationContribution } from './electron-main-application';
|
|
55
|
+
import { Disposable, DisposableCollection, isOSX, MaybePromise } from '../common';
|
|
56
|
+
import { createDisposableListener } from './event-utils';
|
|
57
|
+
|
|
58
|
+
@injectable()
|
|
59
|
+
export class TheiaMainApi implements ElectronMainApplicationContribution {
|
|
60
|
+
@inject(ElectronSecurityToken)
|
|
61
|
+
protected electronSecurityToken: ElectronSecurityToken;
|
|
62
|
+
|
|
63
|
+
protected readonly openPopups = new Map<number, Menu>();
|
|
64
|
+
|
|
65
|
+
onStart(application: ElectronMainApplication): MaybePromise<void> {
|
|
66
|
+
// electron security token
|
|
67
|
+
ipcMain.handle(CHANNEL_GET_SECURITY_TOKEN, () => this.electronSecurityToken.value);
|
|
68
|
+
|
|
69
|
+
ipcMain.handle(CHANNEL_ATTACH_SECURITY_TOKEN, (event, endpoint) => session.defaultSession.cookies.set({
|
|
70
|
+
url: endpoint,
|
|
71
|
+
name: ElectronSecurityToken,
|
|
72
|
+
value: JSON.stringify(this.electronSecurityToken),
|
|
73
|
+
httpOnly: true,
|
|
74
|
+
sameSite: 'no_restriction'
|
|
75
|
+
}));
|
|
76
|
+
|
|
77
|
+
// application menu
|
|
78
|
+
ipcMain.on(CHANNEL_SET_MENU, (event, menuId: number, menu: MenuDto[]) => {
|
|
79
|
+
let electronMenu: Menu | null;
|
|
80
|
+
if (menu) {
|
|
81
|
+
electronMenu = Menu.buildFromTemplate(this.fromMenuDto(event.sender, menuId, menu));
|
|
82
|
+
} else {
|
|
83
|
+
// eslint-disable-next-line no-null/no-null
|
|
84
|
+
electronMenu = null;
|
|
85
|
+
}
|
|
86
|
+
if (isOSX) {
|
|
87
|
+
Menu.setApplicationMenu(electronMenu);
|
|
88
|
+
} else {
|
|
89
|
+
BrowserWindow.fromWebContents(event.sender)?.setMenu(electronMenu);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
ipcMain.on(CHANNEL_SET_MENU_BAR_VISIBLE, (event, visible: boolean, windowName: string | undefined) => {
|
|
94
|
+
let electronWindow;
|
|
95
|
+
if (windowName) {
|
|
96
|
+
electronWindow = BrowserWindow.getAllWindows().find(win => win.webContents.mainFrame.name === windowName);
|
|
97
|
+
} else {
|
|
98
|
+
electronWindow = BrowserWindow.fromWebContents(event.sender);
|
|
99
|
+
}
|
|
100
|
+
if (electronWindow) {
|
|
101
|
+
electronWindow.setMenuBarVisibility(visible);
|
|
102
|
+
} else {
|
|
103
|
+
console.warn(`There is no known secondary window '${windowName}'. Thus, the menu bar could not be made visible.`);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// popup menu
|
|
108
|
+
ipcMain.handle(CHANNEL_OPEN_POPUP, (event, menuId, menu, x, y) => {
|
|
109
|
+
const zoom = event.sender.getZoomFactor();
|
|
110
|
+
// TODO: Remove the offset once Electron fixes https://github.com/electron/electron/issues/31641
|
|
111
|
+
const offset = process.platform === 'win32' ? 0 : 2;
|
|
112
|
+
// x and y values must be Ints or else there is a conversion error
|
|
113
|
+
x = Math.round(x * zoom) + offset;
|
|
114
|
+
y = Math.round(y * zoom) + offset;
|
|
115
|
+
const popup = Menu.buildFromTemplate(this.fromMenuDto(event.sender, menuId, menu));
|
|
116
|
+
this.openPopups.set(menuId, popup);
|
|
117
|
+
popup.popup({
|
|
118
|
+
callback: () => {
|
|
119
|
+
this.openPopups.delete(menuId);
|
|
120
|
+
event.sender.send(CHANNEL_ON_CLOSE_POPUP, menuId);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
ipcMain.handle(CHANNEL_CLOSE_POPUP, (event, handle) => {
|
|
126
|
+
if (this.openPopups.has(handle)) {
|
|
127
|
+
this.openPopups.get(handle)!.closePopup();
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// focus windows for secondary window support
|
|
132
|
+
ipcMain.on(CHANNEL_FOCUS_WINDOW, (event, windowName) => {
|
|
133
|
+
const electronWindow = BrowserWindow.getAllWindows().find(win => win.webContents.mainFrame.name === windowName);
|
|
134
|
+
if (electronWindow) {
|
|
135
|
+
if (electronWindow.isMinimized()) {
|
|
136
|
+
electronWindow.restore();
|
|
137
|
+
}
|
|
138
|
+
electronWindow.focus();
|
|
139
|
+
} else {
|
|
140
|
+
console.warn(`There is no known secondary window '${windowName}'. Thus, the window could not be focussed.`);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
ipcMain.on(CHANNEL_SHOW_ITEM_IN_FOLDER, (event, fsPath) => {
|
|
145
|
+
shell.showItemInFolder(fsPath);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
ipcMain.handle(CHANNEL_GET_TITLE_STYLE_AT_STARTUP, event => application.getTitleBarStyleAtStartup(event.sender));
|
|
149
|
+
|
|
150
|
+
ipcMain.on(CHANNEL_SET_TITLE_STYLE, (event, style) => application.setTitleBarStyle(event.sender, style));
|
|
151
|
+
|
|
152
|
+
ipcMain.on(CHANNEL_MINIMIZE, event => {
|
|
153
|
+
BrowserWindow.fromWebContents(event.sender)?.minimize();
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
ipcMain.on(CHANNEL_IS_MAXIMIZED, event => {
|
|
157
|
+
event.returnValue = BrowserWindow.fromWebContents(event.sender)?.isMaximized();
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
ipcMain.on(CHANNEL_MAXIMIZE, event => {
|
|
161
|
+
BrowserWindow.fromWebContents(event.sender)?.maximize();
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
ipcMain.on(CHANNEL_UNMAXIMIZE, event => {
|
|
165
|
+
BrowserWindow.fromWebContents(event.sender)?.unmaximize();
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
ipcMain.on(CHANNEL_CLOSE, event => {
|
|
169
|
+
BrowserWindow.fromWebContents(event.sender)?.close();
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
ipcMain.on(CHANNEL_RESTART, event => {
|
|
173
|
+
application.restart(event.sender);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
ipcMain.on(CHANNEL_TOGGLE_DEVTOOLS, event => {
|
|
177
|
+
event.sender.toggleDevTools();
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
ipcMain.on(CHANNEL_SET_ZOOM_LEVEL, (event, zoomLevel: number) => {
|
|
181
|
+
event.sender.setZoomLevel(zoomLevel);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
ipcMain.handle(CHANNEL_GET_ZOOM_LEVEL, event => event.sender.getZoomLevel());
|
|
185
|
+
|
|
186
|
+
ipcMain.on(CHANNEL_TOGGLE_FULL_SCREEN, event => {
|
|
187
|
+
const win = BrowserWindow.fromWebContents(event.sender);
|
|
188
|
+
if (win) {
|
|
189
|
+
win.setFullScreen(!win.isFullScreen());
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
ipcMain.on(CHANNEL_IS_FULL_SCREENABLE, event => {
|
|
193
|
+
event.returnValue = BrowserWindow.fromWebContents(event.sender)?.isFullScreenable();
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
ipcMain.on(CHANNEL_IS_FULL_SCREEN, event => {
|
|
197
|
+
event.returnValue = BrowserWindow.fromWebContents(event.sender)?.isFullScreen();
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
ipcMain.on(CHANNEL_READ_CLIPBOARD, event => {
|
|
201
|
+
event.returnValue = clipboard.readText();
|
|
202
|
+
});
|
|
203
|
+
ipcMain.on(CHANNEL_WRITE_CLIPBOARD, (event, text) => {
|
|
204
|
+
clipboard.writeText(text);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
nativeKeymap.onDidChangeKeyboardLayout(() => {
|
|
208
|
+
const newLayout = {
|
|
209
|
+
info: nativeKeymap.getCurrentKeyboardLayout(),
|
|
210
|
+
mapping: nativeKeymap.getKeyMap()
|
|
211
|
+
};
|
|
212
|
+
for (const webContent of webContents.getAllWebContents()) {
|
|
213
|
+
webContent.send('keyboardLayoutChanged', newLayout);
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
fromMenuDto(sender: WebContents, menuId: number, menuDto: InternalMenuDto[]): MenuItemConstructorOptions[] {
|
|
219
|
+
return menuDto.map(dto => {
|
|
220
|
+
|
|
221
|
+
const result: MenuItemConstructorOptions = {
|
|
222
|
+
id: dto.id,
|
|
223
|
+
label: dto.label,
|
|
224
|
+
type: dto.type,
|
|
225
|
+
checked: dto.checked,
|
|
226
|
+
enabled: dto.enabled,
|
|
227
|
+
visible: dto.visible,
|
|
228
|
+
role: dto.role,
|
|
229
|
+
accelerator: dto.accelerator
|
|
230
|
+
};
|
|
231
|
+
if (dto.submenu) {
|
|
232
|
+
result.submenu = this.fromMenuDto(sender, menuId, dto.submenu);
|
|
233
|
+
}
|
|
234
|
+
if (dto.handlerId) {
|
|
235
|
+
result.click = () => {
|
|
236
|
+
sender.send(CHANNEL_INVOKE_MENU, menuId, dto.handlerId);
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
return result;
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
let nextReplyChannel: number = 0;
|
|
245
|
+
|
|
246
|
+
export namespace TheiaRendererAPI {
|
|
247
|
+
export function sendWindowEvent(wc: WebContents, event: WindowEvent): void {
|
|
248
|
+
wc.send(CHANNEL_ON_WINDOW_EVENT, event);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export function requestClose(wc: WebContents, stopReason: StopReason): Promise<boolean> {
|
|
252
|
+
const channelNr = nextReplyChannel++;
|
|
253
|
+
const confirmChannel = `confirm-${channelNr}`;
|
|
254
|
+
const cancelChannel = `cancel-${channelNr}`;
|
|
255
|
+
const disposables = new DisposableCollection();
|
|
256
|
+
|
|
257
|
+
return new Promise<boolean>(resolve => {
|
|
258
|
+
wc.send(CHANNEL_REQUEST_CLOSE, stopReason, confirmChannel, cancelChannel);
|
|
259
|
+
createDisposableListener(ipcMain, confirmChannel, e => {
|
|
260
|
+
resolve(true);
|
|
261
|
+
}, disposables);
|
|
262
|
+
createDisposableListener(ipcMain, cancelChannel, e => {
|
|
263
|
+
resolve(false);
|
|
264
|
+
}, disposables);
|
|
265
|
+
}).finally(() => disposables.dispose());
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export function onRequestReload(wc: WebContents, handler: () => void): Disposable {
|
|
269
|
+
return createWindowListener(wc, CHANNEL_REQUEST_RELOAD, handler);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export function onApplicationStateChanged(wc: WebContents, handler: (state: FrontendApplicationState) => void): Disposable {
|
|
273
|
+
return createWindowListener(wc, CHANNEL_APP_STATE_CHANGED, state => handler(state as FrontendApplicationState));
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export function onIpcData(handler: (sender: WebContents, data: Uint8Array) => void): Disposable {
|
|
277
|
+
return createDisposableListener<IpcMainEvent>(ipcMain, CHANNEL_IPC_CONNECTION, (event, data) => handler(event.sender, data as Uint8Array));
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export function sendData(wc: WebContents, data: Uint8Array): void {
|
|
281
|
+
wc.send(CHANNEL_IPC_CONNECTION, data);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function createWindowListener(wc: WebContents, channel: string, handler: (...args: unknown[]) => unknown): Disposable {
|
|
285
|
+
return createDisposableListener<IpcMainEvent>(ipcMain, channel, (event, ...args) => {
|
|
286
|
+
if (wc.id === event.sender.id) {
|
|
287
|
+
handler(...args);
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
}
|
|
@@ -27,7 +27,7 @@ import { ElectronMessagingService } from './messaging/electron-messaging-service
|
|
|
27
27
|
import { ElectronConnectionHandler } from '../electron-common/messaging/electron-connection-handler';
|
|
28
28
|
import { ElectronSecurityTokenService } from './electron-security-token-service';
|
|
29
29
|
import { TheiaBrowserWindowOptions, TheiaElectronWindow, TheiaElectronWindowFactory, WindowApplicationConfig } from './theia-electron-window';
|
|
30
|
-
import {
|
|
30
|
+
import { TheiaMainApi } from './electron-api-main';
|
|
31
31
|
|
|
32
32
|
const electronSecurityToken: ElectronSecurityToken = { value: v4() };
|
|
33
33
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -44,6 +44,8 @@ export default new ContainerModule(bind => {
|
|
|
44
44
|
bindContributionProvider(bind, ElectronMainApplicationContribution);
|
|
45
45
|
|
|
46
46
|
bind(ElectronMainApplicationContribution).toService(ElectronMessagingContribution);
|
|
47
|
+
bind(TheiaMainApi).toSelf().inSingletonScope();
|
|
48
|
+
bind(ElectronMainApplicationContribution).toService(TheiaMainApi);
|
|
47
49
|
|
|
48
50
|
bind(ElectronMainWindowService).to(ElectronMainWindowServiceImpl).inSingletonScope();
|
|
49
51
|
bind(ElectronConnectionHandler).toDynamicValue(context =>
|
|
@@ -60,7 +62,4 @@ export default new ContainerModule(bind => {
|
|
|
60
62
|
child.bind(WindowApplicationConfig).toConstantValue(config);
|
|
61
63
|
return child.get(TheiaElectronWindow);
|
|
62
64
|
});
|
|
63
|
-
|
|
64
|
-
bind(ElectronNativeKeymap).toSelf().inSingletonScope();
|
|
65
|
-
bind(ElectronMainApplicationContribution).toService(ElectronNativeKeymap);
|
|
66
65
|
});
|
|
@@ -15,8 +15,7 @@
|
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
17
|
import { inject, injectable, named } from 'inversify';
|
|
18
|
-
import
|
|
19
|
-
import { screen, ipcMain, app, BrowserWindow, Event as ElectronEvent, BrowserWindowConstructorOptions, nativeImage } from '../../electron-shared/electron';
|
|
18
|
+
import { screen, app, BrowserWindow, WebContents, Event as ElectronEvent, BrowserWindowConstructorOptions, nativeImage } from '../../electron-shared/electron';
|
|
20
19
|
import * as path from 'path';
|
|
21
20
|
import { Argv } from 'yargs';
|
|
22
21
|
import { AddressInfo } from 'net';
|
|
@@ -32,16 +31,12 @@ import { ElectronSecurityTokenService } from './electron-security-token-service'
|
|
|
32
31
|
import { ElectronSecurityToken } from '../electron-common/electron-token';
|
|
33
32
|
import Storage = require('electron-store');
|
|
34
33
|
import { Disposable, DisposableCollection, isOSX, isWindows } from '../common';
|
|
35
|
-
import {
|
|
36
|
-
RequestTitleBarStyle,
|
|
37
|
-
Restart, StopReason,
|
|
38
|
-
TitleBarStyleAtStartup,
|
|
39
|
-
TitleBarStyleChanged
|
|
40
|
-
} from '../electron-common/messaging/electron-messages';
|
|
41
34
|
import { DEFAULT_WINDOW_HASH } from '../common/window';
|
|
42
35
|
import { TheiaBrowserWindowOptions, TheiaElectronWindow, TheiaElectronWindowFactory } from './theia-electron-window';
|
|
43
36
|
import { ElectronMainApplicationGlobals } from './electron-main-constants';
|
|
44
37
|
import { createDisposableListener } from './event-utils';
|
|
38
|
+
import { TheiaRendererAPI } from './electron-api-main';
|
|
39
|
+
import { StopReason } from '../common/frontend-application-state';
|
|
45
40
|
|
|
46
41
|
export { ElectronMainApplicationGlobals };
|
|
47
42
|
|
|
@@ -156,7 +151,6 @@ export namespace ElectronMainProcessArgv {
|
|
|
156
151
|
|
|
157
152
|
@injectable()
|
|
158
153
|
export class ElectronMainApplication {
|
|
159
|
-
|
|
160
154
|
@inject(ContributionProvider)
|
|
161
155
|
@named(ElectronMainApplicationContribution)
|
|
162
156
|
protected readonly contributions: ContributionProvider<ElectronMainApplicationContribution>;
|
|
@@ -229,6 +223,24 @@ export class ElectronMainApplication {
|
|
|
229
223
|
return isWindows ? 'custom' : 'native';
|
|
230
224
|
}
|
|
231
225
|
|
|
226
|
+
public setTitleBarStyle(webContents: WebContents, style: string): void {
|
|
227
|
+
this.useNativeWindowFrame = isOSX || style === 'native';
|
|
228
|
+
const browserWindow = BrowserWindow.fromWebContents(webContents);
|
|
229
|
+
if (browserWindow) {
|
|
230
|
+
this.saveWindowState(browserWindow);
|
|
231
|
+
} else {
|
|
232
|
+
console.warn(`no BrowserWindow with id: ${webContents.id}`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* @param id the id of the WebContents of the BrowserWindow in question
|
|
238
|
+
* @returns 'native' or 'custom'
|
|
239
|
+
*/
|
|
240
|
+
getTitleBarStyleAtStartup(webContents: WebContents): 'native' | 'custom' {
|
|
241
|
+
return this.didUseNativeWindowFrameOnStart.get(webContents.id) ? 'native' : 'custom';
|
|
242
|
+
}
|
|
243
|
+
|
|
232
244
|
protected async launch(params: ElectronMainExecutionParams): Promise<void> {
|
|
233
245
|
createYargs(params.argv, params.cwd)
|
|
234
246
|
.command('$0 [file]', false,
|
|
@@ -247,11 +259,13 @@ export class ElectronMainApplication {
|
|
|
247
259
|
let options = await asyncOptions;
|
|
248
260
|
options = this.avoidOverlap(options);
|
|
249
261
|
const electronWindow = this.windowFactory(options, this.config);
|
|
250
|
-
const
|
|
262
|
+
const id = electronWindow.window.webContents.id;
|
|
251
263
|
this.windows.set(id, electronWindow);
|
|
252
264
|
electronWindow.onDidClose(() => this.windows.delete(id));
|
|
265
|
+
electronWindow.window.on('maximize', () => TheiaRendererAPI.sendWindowEvent(electronWindow.window.webContents, 'maximize'));
|
|
266
|
+
electronWindow.window.on('unmaximize', () => TheiaRendererAPI.sendWindowEvent(electronWindow.window.webContents, 'unmaximize'));
|
|
267
|
+
electronWindow.window.on('focus', () => TheiaRendererAPI.sendWindowEvent(electronWindow.window.webContents, 'focus'));
|
|
253
268
|
this.attachSaveWindowState(electronWindow.window);
|
|
254
|
-
electronRemoteMain.enable(electronWindow.window.webContents);
|
|
255
269
|
this.configureNativeSecondaryWindowCreation(electronWindow.window);
|
|
256
270
|
return electronWindow.window;
|
|
257
271
|
}
|
|
@@ -292,12 +306,13 @@ export class ElectronMainApplication {
|
|
|
292
306
|
minHeight: 120,
|
|
293
307
|
webPreferences: {
|
|
294
308
|
// `global` is undefined when `true`.
|
|
295
|
-
contextIsolation:
|
|
296
|
-
|
|
297
|
-
nodeIntegration:
|
|
309
|
+
contextIsolation: true,
|
|
310
|
+
sandbox: false,
|
|
311
|
+
nodeIntegration: false,
|
|
298
312
|
// Setting the following option to `true` causes some features to break, somehow.
|
|
299
313
|
// Issue: https://github.com/eclipse-theia/theia/issues/8577
|
|
300
314
|
nodeIntegrationInWorker: false,
|
|
315
|
+
preload: path.resolve(this.globals.THEIA_APP_PROJECT_PATH, 'lib/preload.js').toString()
|
|
301
316
|
},
|
|
302
317
|
...this.config.electron?.windowOptions || {},
|
|
303
318
|
};
|
|
@@ -418,8 +433,8 @@ export class ElectronMainApplication {
|
|
|
418
433
|
}, windowStateListeners);
|
|
419
434
|
createDisposableListener(electronWindow, 'resize', saveWindowStateDelayed, windowStateListeners);
|
|
420
435
|
createDisposableListener(electronWindow, 'move', saveWindowStateDelayed, windowStateListeners);
|
|
421
|
-
windowStateListeners.push(Disposable.create(() => { try { this.didUseNativeWindowFrameOnStart.delete(electronWindow.id); } catch { } }));
|
|
422
|
-
this.didUseNativeWindowFrameOnStart.set(electronWindow.id, this.useNativeWindowFrame);
|
|
436
|
+
windowStateListeners.push(Disposable.create(() => { try { this.didUseNativeWindowFrameOnStart.delete(electronWindow.webContents.id); } catch { } }));
|
|
437
|
+
this.didUseNativeWindowFrameOnStart.set(electronWindow.webContents.id, this.useNativeWindowFrame);
|
|
423
438
|
electronWindow.once('closed', () => windowStateListeners.dispose());
|
|
424
439
|
}
|
|
425
440
|
|
|
@@ -532,24 +547,6 @@ export class ElectronMainApplication {
|
|
|
532
547
|
app.on('will-quit', this.onWillQuit.bind(this));
|
|
533
548
|
app.on('second-instance', this.onSecondInstance.bind(this));
|
|
534
549
|
app.on('window-all-closed', this.onWindowAllClosed.bind(this));
|
|
535
|
-
|
|
536
|
-
ipcMain.on(TitleBarStyleChanged, ({ sender }, titleBarStyle: string) => {
|
|
537
|
-
this.useNativeWindowFrame = isOSX || titleBarStyle === 'native';
|
|
538
|
-
const browserWindow = BrowserWindow.fromId(sender.id);
|
|
539
|
-
if (browserWindow) {
|
|
540
|
-
this.saveWindowState(browserWindow);
|
|
541
|
-
} else {
|
|
542
|
-
console.warn(`no BrowserWindow with id: ${sender.id}`);
|
|
543
|
-
}
|
|
544
|
-
});
|
|
545
|
-
|
|
546
|
-
ipcMain.on(Restart, ({ sender }) => {
|
|
547
|
-
this.restart(sender.id);
|
|
548
|
-
});
|
|
549
|
-
|
|
550
|
-
ipcMain.on(RequestTitleBarStyle, ({ sender }) => {
|
|
551
|
-
sender.send(TitleBarStyleAtStartup, this.didUseNativeWindowFrameOnStart.get(sender.id) ? 'native' : 'custom');
|
|
552
|
-
});
|
|
553
550
|
}
|
|
554
551
|
|
|
555
552
|
protected onWillQuit(event: ElectronEvent): void {
|
|
@@ -573,10 +570,9 @@ export class ElectronMainApplication {
|
|
|
573
570
|
}
|
|
574
571
|
}
|
|
575
572
|
|
|
576
|
-
|
|
573
|
+
public async restart(webContents: WebContents): Promise<void> {
|
|
577
574
|
this.restarting = true;
|
|
578
|
-
const
|
|
579
|
-
const wrapper = this.windows.get(window?.id as number); // If it's not a number, we won't get anything.
|
|
575
|
+
const wrapper = this.windows.get(webContents.id);
|
|
580
576
|
if (wrapper) {
|
|
581
577
|
const listener = wrapper.onDidClose(async () => {
|
|
582
578
|
listener.dispose();
|
|
@@ -14,16 +14,17 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
import {
|
|
17
|
+
import { WebContents } from '@theia/electron/shared/electron';
|
|
18
18
|
import { inject, injectable, named, postConstruct } from 'inversify';
|
|
19
19
|
import { ContributionProvider } from '../../common/contribution-provider';
|
|
20
20
|
import { MessagingContribution } from '../../node/messaging/messaging-contribution';
|
|
21
|
-
import { ElectronConnectionHandler
|
|
21
|
+
import { ElectronConnectionHandler } from '../../electron-common/messaging/electron-connection-handler';
|
|
22
22
|
import { ElectronMainApplicationContribution } from '../electron-main-application';
|
|
23
23
|
import { ElectronMessagingService } from './electron-messaging-service';
|
|
24
24
|
import { AbstractChannel, Channel, ChannelMultiplexer, MessageProvider } from '../../common/message-rpc/channel';
|
|
25
|
-
import { Emitter, WriteBuffer } from '../../common';
|
|
25
|
+
import { ConnectionHandler, Emitter, WriteBuffer } from '../../common';
|
|
26
26
|
import { Uint8ArrayReadBuffer, Uint8ArrayWriteBuffer } from '../../common/message-rpc/uint8-array-message-buffer';
|
|
27
|
+
import { TheiaRendererAPI } from '../electron-api-main';
|
|
27
28
|
|
|
28
29
|
/**
|
|
29
30
|
* This component replicates the role filled by `MessagingContribution` but for Electron.
|
|
@@ -40,7 +41,7 @@ export class ElectronMessagingContribution implements ElectronMainApplicationCon
|
|
|
40
41
|
protected readonly messagingContributions: ContributionProvider<ElectronMessagingService.Contribution>;
|
|
41
42
|
|
|
42
43
|
@inject(ContributionProvider) @named(ElectronConnectionHandler)
|
|
43
|
-
protected readonly connectionHandlers: ContributionProvider<
|
|
44
|
+
protected readonly connectionHandlers: ContributionProvider<ConnectionHandler>;
|
|
44
45
|
|
|
45
46
|
protected readonly channelHandlers = new MessagingContribution.ConnectionHandlers<Channel>();
|
|
46
47
|
/**
|
|
@@ -50,13 +51,10 @@ export class ElectronMessagingContribution implements ElectronMainApplicationCon
|
|
|
50
51
|
|
|
51
52
|
@postConstruct()
|
|
52
53
|
protected init(): void {
|
|
53
|
-
|
|
54
|
-
this.handleIpcEvent(event, data);
|
|
55
|
-
});
|
|
54
|
+
TheiaRendererAPI.onIpcData((sender, data) => this.handleIpcEvent(sender, data));
|
|
56
55
|
}
|
|
57
56
|
|
|
58
|
-
protected handleIpcEvent(
|
|
59
|
-
const sender = event.sender;
|
|
57
|
+
protected handleIpcEvent(sender: WebContents, data: Uint8Array): void {
|
|
60
58
|
// Get the multiplexer for a given window id
|
|
61
59
|
try {
|
|
62
60
|
const windowChannelData = this.windowChannelMultiplexer.get(sender.id) ?? this.createWindowChannelData(sender);
|
|
@@ -133,7 +131,7 @@ export class ElectronWebContentChannel extends AbstractChannel {
|
|
|
133
131
|
|
|
134
132
|
writer.onCommit(buffer => {
|
|
135
133
|
if (!this.sender.isDestroyed()) {
|
|
136
|
-
this.sender
|
|
134
|
+
TheiaRendererAPI.sendData(this.sender, buffer);
|
|
137
135
|
}
|
|
138
136
|
});
|
|
139
137
|
|
|
@@ -15,15 +15,15 @@
|
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
17
|
import { FrontendApplicationConfig } from '@theia/application-package';
|
|
18
|
-
import { FrontendApplicationState } from '../common/frontend-application-state';
|
|
19
|
-
import {
|
|
20
|
-
import { BrowserWindow, BrowserWindowConstructorOptions, ipcMain, IpcMainEvent } from '../../electron-shared/electron';
|
|
18
|
+
import { FrontendApplicationState, StopReason } from '../common/frontend-application-state';
|
|
19
|
+
import { BrowserWindow, BrowserWindowConstructorOptions } from '../../electron-shared/electron';
|
|
21
20
|
import { inject, injectable, postConstruct } from '../../shared/inversify';
|
|
22
21
|
import { ElectronMainApplicationGlobals } from './electron-main-constants';
|
|
23
22
|
import { DisposableCollection, Emitter, Event } from '../common';
|
|
24
23
|
import { createDisposableListener } from './event-utils';
|
|
25
24
|
import { URI } from '../common/uri';
|
|
26
25
|
import { FileUri } from '../node/file-uri';
|
|
26
|
+
import { TheiaRendererAPI } from './electron-api-main';
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* Theia tracks the maximized state of Electron Browser Windows.
|
|
@@ -138,22 +138,7 @@ export class TheiaElectronWindow {
|
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
protected checkSafeToStop(reason: StopReason): Promise<boolean> {
|
|
141
|
-
|
|
142
|
-
const cancelChannel = `notSafeToClose-${this._window.id}`;
|
|
143
|
-
const temporaryDisposables = new DisposableCollection();
|
|
144
|
-
return new Promise<boolean>(resolve => {
|
|
145
|
-
this._window.webContents.send(CLOSE_REQUESTED_SIGNAL, { confirmChannel, cancelChannel, reason });
|
|
146
|
-
createDisposableListener(ipcMain, confirmChannel, (e: IpcMainEvent) => {
|
|
147
|
-
if (this.isSender(e)) {
|
|
148
|
-
resolve(true);
|
|
149
|
-
}
|
|
150
|
-
}, temporaryDisposables);
|
|
151
|
-
createDisposableListener(ipcMain, cancelChannel, (e: IpcMainEvent) => {
|
|
152
|
-
if (this.isSender(e)) {
|
|
153
|
-
resolve(false);
|
|
154
|
-
}
|
|
155
|
-
}, temporaryDisposables);
|
|
156
|
-
}).finally(() => temporaryDisposables.dispose());
|
|
141
|
+
return TheiaRendererAPI.requestClose(this.window.webContents, reason);
|
|
157
142
|
}
|
|
158
143
|
|
|
159
144
|
protected restoreMaximizedState(): void {
|
|
@@ -165,23 +150,13 @@ export class TheiaElectronWindow {
|
|
|
165
150
|
}
|
|
166
151
|
|
|
167
152
|
protected trackApplicationState(): void {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
}, this.toDispose);
|
|
153
|
+
this.toDispose.push(TheiaRendererAPI.onApplicationStateChanged(this.window.webContents, state => {
|
|
154
|
+
this.applicationState = state;
|
|
155
|
+
}));
|
|
173
156
|
}
|
|
174
157
|
|
|
175
158
|
protected attachReloadListener(): void {
|
|
176
|
-
|
|
177
|
-
if (this.isSender(e)) {
|
|
178
|
-
this.reload();
|
|
179
|
-
}
|
|
180
|
-
}, this.toDispose);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
protected isSender(e: IpcMainEvent): boolean {
|
|
184
|
-
return BrowserWindow.fromId(e.sender.id) === this._window;
|
|
159
|
+
this.toDispose.push(TheiaRendererAPI.onRequestReload(this.window.webContents, () => this.reload()));
|
|
185
160
|
}
|
|
186
161
|
|
|
187
162
|
dispose(): void {
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import * as express from 'express';
|
|
18
18
|
import { inject, injectable } from 'inversify';
|
|
19
|
+
import { nls } from '../../common/nls';
|
|
19
20
|
import { Deferred } from '../../common/promise-util';
|
|
20
21
|
import { BackendApplicationContribution } from '../backend-application';
|
|
21
22
|
import { LocalizationRegistry } from './localization-contribution';
|
|
@@ -44,7 +45,7 @@ export class LocalizationBackendContribution implements BackendApplicationContri
|
|
|
44
45
|
app.get('/i18n/:locale', async (req, res) => {
|
|
45
46
|
await this.waitForInitialization();
|
|
46
47
|
let locale = req.params.locale;
|
|
47
|
-
locale = this.localizationProvider.getAvailableLanguages().some(e => e.languageId === locale) ? locale :
|
|
48
|
+
locale = this.localizationProvider.getAvailableLanguages().some(e => e.languageId === locale) ? locale : nls.defaultLocale;
|
|
48
49
|
this.localizationProvider.setCurrentLanguage(locale);
|
|
49
50
|
res.send(this.localizationProvider.loadLocalization(locale));
|
|
50
51
|
});
|
|
@@ -15,13 +15,14 @@
|
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
17
|
import { injectable } from 'inversify';
|
|
18
|
+
import { nls } from '../../common/nls';
|
|
18
19
|
import { LanguageInfo, Localization } from '../../common/i18n/localization';
|
|
19
20
|
|
|
20
21
|
@injectable()
|
|
21
22
|
export class LocalizationProvider {
|
|
22
23
|
|
|
23
24
|
protected localizations: Localization[] = [];
|
|
24
|
-
protected currentLanguage =
|
|
25
|
+
protected currentLanguage = nls.defaultLocale;
|
|
25
26
|
|
|
26
27
|
addLocalizations(...localizations: Localization[]): void {
|
|
27
28
|
this.localizations.push(...localizations);
|