@theia/core 1.43.1 → 1.44.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 +6 -6
- package/lib/browser/common-frontend-contribution.d.ts +4 -0
- package/lib/browser/common-frontend-contribution.d.ts.map +1 -1
- package/lib/browser/common-frontend-contribution.js +16 -1
- package/lib/browser/common-frontend-contribution.js.map +1 -1
- package/lib/browser/frontend-application-module.d.ts.map +1 -1
- package/lib/browser/frontend-application-module.js +3 -0
- package/lib/browser/frontend-application-module.js.map +1 -1
- package/lib/browser/icon-theme-contribution.d.ts +1 -0
- package/lib/browser/icon-theme-contribution.d.ts.map +1 -1
- package/lib/browser/icon-theme-contribution.js +1 -0
- package/lib/browser/icon-theme-contribution.js.map +1 -1
- package/lib/browser/icon-theme-service.d.ts +1 -0
- package/lib/browser/icon-theme-service.d.ts.map +1 -1
- package/lib/browser/icon-theme-service.js.map +1 -1
- package/lib/browser/language-icon-provider.d.ts +15 -0
- package/lib/browser/language-icon-provider.d.ts.map +1 -0
- package/lib/browser/language-icon-provider.js +74 -0
- package/lib/browser/language-icon-provider.js.map +1 -0
- package/lib/browser/language-service.d.ts +22 -0
- package/lib/browser/language-service.d.ts.map +1 -1
- package/lib/browser/language-service.js +28 -0
- package/lib/browser/language-service.js.map +1 -1
- package/lib/common/contribution-filter/contribution-filter.d.ts +9 -0
- package/lib/common/contribution-filter/contribution-filter.d.ts.map +1 -1
- package/lib/common/event.js +1 -1
- package/lib/common/event.js.map +1 -1
- package/lib/common/nls.js +12 -1
- package/lib/common/nls.js.map +1 -1
- package/lib/electron-browser/preload.d.ts.map +1 -1
- package/lib/electron-browser/preload.js +1 -0
- package/lib/electron-browser/preload.js.map +1 -1
- package/lib/electron-browser/window/electron-secondary-window-service.d.ts +1 -1
- package/lib/electron-browser/window/electron-secondary-window-service.d.ts.map +1 -1
- package/lib/electron-browser/window/electron-window-preferences.js +1 -1
- package/lib/electron-browser/window/electron-window-preferences.js.map +1 -1
- package/lib/electron-common/electron-api.d.ts +1 -0
- package/lib/electron-common/electron-api.d.ts.map +1 -1
- package/lib/electron-common/electron-api.js.map +1 -1
- package/lib/electron-main/electron-main-application.d.ts +2 -0
- package/lib/electron-main/electron-main-application.d.ts.map +1 -1
- package/lib/electron-main/electron-main-application.js +26 -4
- package/lib/electron-main/electron-main-application.js.map +1 -1
- package/lib/node/backend-application.d.ts +2 -0
- package/lib/node/backend-application.d.ts.map +1 -1
- package/lib/node/backend-application.js +11 -9
- package/lib/node/backend-application.js.map +1 -1
- package/lib/node/cli.d.ts +1 -1
- package/lib/node/cli.d.ts.map +1 -1
- package/lib/node/cli.js +9 -5
- package/lib/node/cli.js.map +1 -1
- package/lib/node/cli.spec.js +3 -3
- package/lib/node/cli.spec.js.map +1 -1
- package/lib/node/env-variables/env-variables-server.d.ts +3 -0
- package/lib/node/env-variables/env-variables-server.d.ts.map +1 -1
- package/lib/node/env-variables/env-variables-server.js +25 -1
- package/lib/node/env-variables/env-variables-server.js.map +1 -1
- package/lib/node/i18n/localization-server.d.ts +1 -1
- package/lib/node/i18n/localization-server.d.ts.map +1 -1
- package/lib/node/messaging/ipc-protocol.js +1 -1
- package/lib/node/messaging/ipc-protocol.js.map +1 -1
- package/package.json +6 -6
- package/src/browser/common-frontend-contribution.ts +15 -0
- package/src/browser/frontend-application-module.ts +3 -0
- package/src/browser/icon-theme-contribution.ts +1 -0
- package/src/browser/icon-theme-service.ts +1 -0
- package/src/browser/language-icon-provider.ts +55 -0
- package/src/browser/language-service.ts +34 -0
- package/src/browser/style/index.css +1 -0
- package/src/browser/style/os.css +87 -0
- package/src/common/contribution-filter/contribution-filter.ts +9 -0
- package/src/common/event.ts +1 -1
- package/src/common/i18n/nls.metadata.json +7143 -6953
- package/src/common/nls.ts +12 -1
- package/src/electron-browser/preload.ts +1 -0
- package/src/electron-browser/window/electron-secondary-window-service.ts +1 -1
- package/src/electron-browser/window/electron-window-preferences.ts +1 -1
- package/src/electron-common/electron-api.ts +1 -0
- package/src/electron-main/electron-main-application.ts +28 -5
- package/src/node/backend-application.ts +14 -11
- package/src/node/cli.spec.ts +3 -3
- package/src/node/cli.ts +9 -5
- package/src/node/env-variables/env-variables-server.ts +21 -1
- package/src/node/i18n/localization-server.ts +1 -1
- package/src/node/messaging/ipc-protocol.ts +1 -1
package/src/common/nls.ts
CHANGED
|
@@ -81,6 +81,10 @@ interface NlsInfo {
|
|
|
81
81
|
|
|
82
82
|
class LocalizationKeyProvider {
|
|
83
83
|
|
|
84
|
+
private preferredKeys = new Set([
|
|
85
|
+
// We only want the `File` translation used in the menu
|
|
86
|
+
'vscode/fileActions.contribution/filesCategory'
|
|
87
|
+
]);
|
|
84
88
|
private data = this.buildData();
|
|
85
89
|
|
|
86
90
|
get(defaultValue: string): string | undefined {
|
|
@@ -100,9 +104,16 @@ class LocalizationKeyProvider {
|
|
|
100
104
|
const keys: NlsKeys = bundles.keys;
|
|
101
105
|
const messages: Record<string, string[]> = bundles.messages;
|
|
102
106
|
const data = new Map<string, string>();
|
|
107
|
+
const foundPreferredKeys = new Set<string>();
|
|
103
108
|
const keysAndMessages = this.buildKeyMessageTuples(keys, messages);
|
|
104
109
|
for (const { key, message } of keysAndMessages) {
|
|
105
|
-
|
|
110
|
+
if (!foundPreferredKeys.has(message)) {
|
|
111
|
+
data.set(message, key);
|
|
112
|
+
if (this.preferredKeys.has(key)) {
|
|
113
|
+
// Prevent messages with preferred keys to be overridden
|
|
114
|
+
foundPreferredKeys.add(message);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
106
117
|
}
|
|
107
118
|
// Second pass adds each message again in upper case, if the message doesn't already exist in upper case
|
|
108
119
|
// The second pass is needed to not accidentally override any translations which actually use the upper case message
|
|
@@ -207,6 +207,7 @@ const api: TheiaCoreAPI = {
|
|
|
207
207
|
sendData: data => {
|
|
208
208
|
ipcRenderer.send(CHANNEL_IPC_CONNECTION, data);
|
|
209
209
|
},
|
|
210
|
+
useNativeElements: !('THEIA_ELECTRON_DISABLE_NATIVE_ELEMENTS' in process.env && process.env.THEIA_ELECTRON_DISABLE_NATIVE_ELEMENTS === '1')
|
|
210
211
|
};
|
|
211
212
|
|
|
212
213
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import { injectable } from 'inversify';
|
|
18
18
|
import { DefaultSecondaryWindowService } from '../../browser/window/default-secondary-window-service';
|
|
19
|
-
import { ApplicationShell, ExtractableWidget } from '
|
|
19
|
+
import { ApplicationShell, ExtractableWidget } from '../../browser';
|
|
20
20
|
|
|
21
21
|
@injectable()
|
|
22
22
|
export class ElectronSecondaryWindowService extends DefaultSecondaryWindowService {
|
|
@@ -46,7 +46,7 @@ export const electronWindowPreferencesSchema: PreferenceSchema = {
|
|
|
46
46
|
default: isWindows ? 'custom' : 'native',
|
|
47
47
|
scope: 'application',
|
|
48
48
|
// eslint-disable-next-line max-len
|
|
49
|
-
description: nls.localizeByDefault('Adjust the appearance of the window title bar. On Linux and Windows, this setting also affects the application and context menu appearances. Changes require a full restart to apply.'),
|
|
49
|
+
description: nls.localizeByDefault('Adjust the appearance of the window title bar to be native by the OS or custom. On Linux and Windows, this setting also affects the application and context menu appearances. Changes require a full restart to apply.'),
|
|
50
50
|
included: !isOSX
|
|
51
51
|
},
|
|
52
52
|
}
|
|
@@ -20,6 +20,7 @@ import * as path from 'path';
|
|
|
20
20
|
import { Argv } from 'yargs';
|
|
21
21
|
import { AddressInfo } from 'net';
|
|
22
22
|
import { promises as fs } from 'fs';
|
|
23
|
+
import { existsSync, mkdirSync } from 'fs-extra';
|
|
23
24
|
import { fork, ForkOptions } from 'child_process';
|
|
24
25
|
import { DefaultTheme, FrontendApplicationConfig } from '@theia/application-package/lib/application-props';
|
|
25
26
|
import URI from '../common/uri';
|
|
@@ -171,6 +172,8 @@ export class ElectronMainApplication {
|
|
|
171
172
|
@inject(TheiaElectronWindowFactory)
|
|
172
173
|
protected readonly windowFactory: TheiaElectronWindowFactory;
|
|
173
174
|
|
|
175
|
+
protected isPortable = this.makePortable();
|
|
176
|
+
|
|
174
177
|
protected readonly electronStore = new Storage<{
|
|
175
178
|
windowstate?: TheiaBrowserWindowOptions
|
|
176
179
|
}>();
|
|
@@ -194,7 +197,22 @@ export class ElectronMainApplication {
|
|
|
194
197
|
return this._config;
|
|
195
198
|
}
|
|
196
199
|
|
|
200
|
+
protected makePortable(): boolean {
|
|
201
|
+
const dataFolderPath = path.join(app.getAppPath(), 'data');
|
|
202
|
+
const appDataPath = path.join(dataFolderPath, 'app-data');
|
|
203
|
+
if (existsSync(dataFolderPath)) {
|
|
204
|
+
if (!existsSync(appDataPath)) {
|
|
205
|
+
mkdirSync(appDataPath);
|
|
206
|
+
}
|
|
207
|
+
app.setPath('userData', appDataPath);
|
|
208
|
+
return true;
|
|
209
|
+
} else {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
197
214
|
async start(config: FrontendApplicationConfig): Promise<void> {
|
|
215
|
+
const args = this.processArgv.getProcessArgvWithoutBin(process.argv);
|
|
198
216
|
this.useNativeWindowFrame = this.getTitleBarStyle(config) === 'native';
|
|
199
217
|
this._config = config;
|
|
200
218
|
this.hookApplicationEvents();
|
|
@@ -206,12 +224,15 @@ export class ElectronMainApplication {
|
|
|
206
224
|
await this.startContributions();
|
|
207
225
|
await this.launch({
|
|
208
226
|
secondInstance: false,
|
|
209
|
-
argv:
|
|
227
|
+
argv: args,
|
|
210
228
|
cwd: process.cwd()
|
|
211
229
|
});
|
|
212
230
|
}
|
|
213
231
|
|
|
214
232
|
protected getTitleBarStyle(config: FrontendApplicationConfig): 'native' | 'custom' {
|
|
233
|
+
if ('THEIA_ELECTRON_DISABLE_NATIVE_ELEMENTS' in process.env && process.env.THEIA_ELECTRON_DISABLE_NATIVE_ELEMENTS === '1') {
|
|
234
|
+
return 'custom';
|
|
235
|
+
}
|
|
215
236
|
if (isOSX) {
|
|
216
237
|
return 'native';
|
|
217
238
|
}
|
|
@@ -256,7 +277,9 @@ export class ElectronMainApplication {
|
|
|
256
277
|
}
|
|
257
278
|
|
|
258
279
|
protected showInitialWindow(): void {
|
|
259
|
-
if (this.config.electron.showWindowEarly
|
|
280
|
+
if (this.config.electron.showWindowEarly &&
|
|
281
|
+
!('THEIA_ELECTRON_NO_EARLY_WINDOW' in process.env && process.env.THEIA_ELECTRON_NO_EARLY_WINDOW === '1')) {
|
|
282
|
+
console.log('Showing main window early');
|
|
260
283
|
app.whenReady().then(async () => {
|
|
261
284
|
const options = await this.getLastWindowOptions();
|
|
262
285
|
this.initialWindow = await this.createWindow({ ...options });
|
|
@@ -461,7 +484,7 @@ export class ElectronMainApplication {
|
|
|
461
484
|
*/
|
|
462
485
|
protected attachSaveWindowState(electronWindow: BrowserWindow): void {
|
|
463
486
|
const windowStateListeners = new DisposableCollection();
|
|
464
|
-
let delayedSaveTimeout: NodeJS.
|
|
487
|
+
let delayedSaveTimeout: NodeJS.Timeout | undefined;
|
|
465
488
|
const saveWindowStateDelayed = () => {
|
|
466
489
|
if (delayedSaveTimeout) {
|
|
467
490
|
clearTimeout(delayedSaveTimeout);
|
|
@@ -547,8 +570,8 @@ export class ElectronMainApplication {
|
|
|
547
570
|
backendProcess.on('error', error => {
|
|
548
571
|
reject(error);
|
|
549
572
|
});
|
|
550
|
-
backendProcess.on('exit',
|
|
551
|
-
reject(
|
|
573
|
+
backendProcess.on('exit', code => {
|
|
574
|
+
reject(code);
|
|
552
575
|
});
|
|
553
576
|
app.on('quit', () => {
|
|
554
577
|
// Only issue a kill signal if the backend process is running.
|
|
@@ -170,6 +170,8 @@ export class BackendApplication {
|
|
|
170
170
|
@inject(Stopwatch)
|
|
171
171
|
protected readonly stopwatch: Stopwatch;
|
|
172
172
|
|
|
173
|
+
private _configured: Promise<void>;
|
|
174
|
+
|
|
173
175
|
constructor(
|
|
174
176
|
@inject(ContributionProvider) @named(BackendApplicationContribution)
|
|
175
177
|
protected readonly contributionsProvider: ContributionProvider<BackendApplicationContribution>,
|
|
@@ -198,7 +200,7 @@ export class BackendApplication {
|
|
|
198
200
|
}
|
|
199
201
|
|
|
200
202
|
protected async initialize(): Promise<void> {
|
|
201
|
-
|
|
203
|
+
await Promise.all(this.contributionsProvider.getContributions().map(async contribution => {
|
|
202
204
|
if (contribution.initialize) {
|
|
203
205
|
try {
|
|
204
206
|
await this.measure(contribution.constructor.name + '.initialize',
|
|
@@ -208,18 +210,20 @@ export class BackendApplication {
|
|
|
208
210
|
console.error('Could not initialize contribution', error);
|
|
209
211
|
}
|
|
210
212
|
}
|
|
211
|
-
}
|
|
213
|
+
}));
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
get configured(): Promise<void> {
|
|
217
|
+
return this._configured;
|
|
212
218
|
}
|
|
213
219
|
|
|
214
220
|
@postConstruct()
|
|
215
221
|
protected init(): void {
|
|
216
|
-
this.configure();
|
|
222
|
+
this._configured = this.configure();
|
|
217
223
|
}
|
|
218
224
|
|
|
219
225
|
protected async configure(): Promise<void> {
|
|
220
|
-
|
|
221
|
-
// concurrent initialize/configure in undefined order if they provide both
|
|
222
|
-
this.initialize();
|
|
226
|
+
await this.initialize();
|
|
223
227
|
|
|
224
228
|
this.app.get('*.js', this.serveGzipped.bind(this, 'text/javascript'));
|
|
225
229
|
this.app.get('*.js.map', this.serveGzipped.bind(this, 'application/json'));
|
|
@@ -233,17 +237,16 @@ export class BackendApplication {
|
|
|
233
237
|
this.app.get('*.woff', this.serveGzipped.bind(this, 'font/woff'));
|
|
234
238
|
this.app.get('*.woff2', this.serveGzipped.bind(this, 'font/woff2'));
|
|
235
239
|
|
|
236
|
-
|
|
240
|
+
await Promise.all(this.contributionsProvider.getContributions().map(async contribution => {
|
|
237
241
|
if (contribution.configure) {
|
|
238
242
|
try {
|
|
239
|
-
await
|
|
240
|
-
() => contribution.configure!(this.app)
|
|
241
|
-
);
|
|
243
|
+
await contribution.configure!(this.app);
|
|
242
244
|
} catch (error) {
|
|
243
245
|
console.error('Could not configure contribution', error);
|
|
244
246
|
}
|
|
245
247
|
}
|
|
246
|
-
}
|
|
248
|
+
}));
|
|
249
|
+
console.info('configured all backend app contributions');
|
|
247
250
|
}
|
|
248
251
|
|
|
249
252
|
use(...handlers: express.Handler[]): void {
|
package/src/node/cli.spec.ts
CHANGED
|
@@ -44,7 +44,7 @@ describe('CliManager', () => {
|
|
|
44
44
|
value.resolve(args['foo'] as string);
|
|
45
45
|
}
|
|
46
46
|
});
|
|
47
|
-
await manager.initializeCli(['-f', 'bla']);
|
|
47
|
+
await manager.initializeCli(['-f', 'bla'], () => Promise.resolve(), () => Promise.resolve());
|
|
48
48
|
chai.assert.equal(await value.promise, 'bla');
|
|
49
49
|
});
|
|
50
50
|
|
|
@@ -59,14 +59,14 @@ describe('CliManager', () => {
|
|
|
59
59
|
value.resolve(args['bar'] as string);
|
|
60
60
|
}
|
|
61
61
|
});
|
|
62
|
-
await manager.initializeCli(['--foo']);
|
|
62
|
+
await manager.initializeCli(['--foo'], () => Promise.resolve(), () => Promise.resolve());
|
|
63
63
|
chai.assert.equal(await value.promise, 'my-default');
|
|
64
64
|
});
|
|
65
65
|
|
|
66
66
|
it('prints help and exits', async () =>
|
|
67
67
|
assertExits(async () => {
|
|
68
68
|
const manager = new TestCliManager();
|
|
69
|
-
await manager.initializeCli(['--help']);
|
|
69
|
+
await manager.initializeCli(['--help'], () => Promise.resolve(), () => Promise.resolve());
|
|
70
70
|
})
|
|
71
71
|
);
|
|
72
72
|
});
|
package/src/node/cli.ts
CHANGED
|
@@ -35,7 +35,7 @@ export class CliManager {
|
|
|
35
35
|
constructor(@inject(ContributionProvider) @named(CliContribution)
|
|
36
36
|
protected readonly contributionsProvider: ContributionProvider<CliContribution>) { }
|
|
37
37
|
|
|
38
|
-
async initializeCli(argv: string[]): Promise<void> {
|
|
38
|
+
async initializeCli<T>(argv: string[], postSetArguments: () => Promise<void>, defaultCommand: () => Promise<void>): Promise<void> {
|
|
39
39
|
const pack = require('../../package.json');
|
|
40
40
|
const version = pack.version;
|
|
41
41
|
const command = yargs.version(version);
|
|
@@ -43,14 +43,18 @@ export class CliManager {
|
|
|
43
43
|
for (const contrib of this.contributionsProvider.getContributions()) {
|
|
44
44
|
contrib.configure(command);
|
|
45
45
|
}
|
|
46
|
-
|
|
46
|
+
await command
|
|
47
47
|
.detectLocale(false)
|
|
48
48
|
.showHelpOnFail(false, 'Specify --help for available options')
|
|
49
49
|
.help('help')
|
|
50
|
+
.middleware(async args => {
|
|
51
|
+
for (const contrib of this.contributionsProvider.getContributions()) {
|
|
52
|
+
await contrib.setArguments(args);
|
|
53
|
+
}
|
|
54
|
+
await postSetArguments();
|
|
55
|
+
})
|
|
56
|
+
.command('$0', false, () => { }, defaultCommand)
|
|
50
57
|
.parse(argv);
|
|
51
|
-
for (const contrib of this.contributionsProvider.getContributions()) {
|
|
52
|
-
await contrib.setArguments(args);
|
|
53
|
-
}
|
|
54
58
|
}
|
|
55
59
|
|
|
56
60
|
protected isExit(): boolean {
|
|
@@ -18,6 +18,7 @@ import { join } from 'path';
|
|
|
18
18
|
import { homedir } from 'os';
|
|
19
19
|
import { injectable } from 'inversify';
|
|
20
20
|
import * as drivelist from 'drivelist';
|
|
21
|
+
import { pathExists, mkdir } from 'fs-extra';
|
|
21
22
|
import { EnvVariable, EnvVariablesServer } from '../../common/env-variables';
|
|
22
23
|
import { isWindows } from '../../common/os';
|
|
23
24
|
import { FileUri } from '../file-uri';
|
|
@@ -28,6 +29,7 @@ export class EnvVariablesServerImpl implements EnvVariablesServer {
|
|
|
28
29
|
protected readonly envs: { [key: string]: EnvVariable } = {};
|
|
29
30
|
protected readonly homeDirUri = FileUri.create(homedir()).toString();
|
|
30
31
|
protected readonly configDirUri: Promise<string>;
|
|
32
|
+
protected readonly pathExistenceCache: { [key: string]: boolean } = {};
|
|
31
33
|
|
|
32
34
|
constructor() {
|
|
33
35
|
this.configDirUri = this.createConfigDirUri();
|
|
@@ -43,7 +45,25 @@ export class EnvVariablesServerImpl implements EnvVariablesServer {
|
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
protected async createConfigDirUri(): Promise<string> {
|
|
46
|
-
|
|
48
|
+
let dataFolderPath: string = '';
|
|
49
|
+
if (process.env.THEIA_APP_PROJECT_PATH) {
|
|
50
|
+
dataFolderPath = join(process.env.THEIA_APP_PROJECT_PATH, 'data');
|
|
51
|
+
}
|
|
52
|
+
const userDataPath = join(dataFolderPath, 'user-data');
|
|
53
|
+
const dataFolderExists = this.pathExistenceCache[dataFolderPath] ??= await pathExists(dataFolderPath);
|
|
54
|
+
if (dataFolderExists) {
|
|
55
|
+
const userDataExists = this.pathExistenceCache[userDataPath] ??= await pathExists(userDataPath);
|
|
56
|
+
if (userDataExists) {
|
|
57
|
+
process.env.THEIA_CONFIG_DIR = userDataPath;
|
|
58
|
+
} else {
|
|
59
|
+
await mkdir(userDataPath);
|
|
60
|
+
process.env.THEIA_CONFIG_DIR = userDataPath;
|
|
61
|
+
this.pathExistenceCache[userDataPath] = true;
|
|
62
|
+
}
|
|
63
|
+
} else {
|
|
64
|
+
process.env.THEIA_CONFIG_DIR = join(homedir(), '.theia');
|
|
65
|
+
}
|
|
66
|
+
return FileUri.create(process.env.THEIA_CONFIG_DIR).toString();
|
|
47
67
|
}
|
|
48
68
|
|
|
49
69
|
async getExecPath(): Promise<string> {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
17
|
import { inject, injectable } from 'inversify';
|
|
18
|
-
import { Localization } from '
|
|
18
|
+
import { Localization } from '../../common/i18n/localization';
|
|
19
19
|
import { LocalizationServer } from '../../common/i18n/localization-server';
|
|
20
20
|
import { nls } from '../../common/nls';
|
|
21
21
|
import { Deferred } from '../../common/promise-util';
|