@theia/core 1.34.0 → 1.35.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/i18n/nls.cs.json +3 -5
- package/i18n/nls.de.json +3 -5
- package/i18n/nls.es.json +3 -5
- package/i18n/nls.fr.json +3 -5
- package/i18n/nls.hu.json +3 -5
- package/i18n/nls.it.json +3 -5
- package/i18n/nls.ja.json +3 -5
- package/i18n/nls.json +3 -5
- package/i18n/nls.pl.json +3 -5
- package/i18n/nls.pt-br.json +3 -5
- package/i18n/nls.pt-pt.json +3 -5
- package/i18n/nls.ru.json +3 -5
- package/i18n/nls.zh-cn.json +3 -5
- package/lib/browser/common-frontend-contribution.d.ts +2 -1
- package/lib/browser/common-frontend-contribution.d.ts.map +1 -1
- package/lib/browser/common-frontend-contribution.js +15 -7
- package/lib/browser/common-frontend-contribution.js.map +1 -1
- package/lib/browser/core-preferences.d.ts +1 -0
- package/lib/browser/core-preferences.d.ts.map +1 -1
- package/lib/browser/core-preferences.js +8 -11
- package/lib/browser/core-preferences.js.map +1 -1
- package/lib/browser/dialogs.d.ts +12 -0
- package/lib/browser/dialogs.d.ts.map +1 -1
- package/lib/browser/dialogs.js +70 -1
- package/lib/browser/dialogs.js.map +1 -1
- package/lib/browser/i18n/language-quick-pick-service.d.ts +2 -3
- package/lib/browser/i18n/language-quick-pick-service.d.ts.map +1 -1
- package/lib/browser/i18n/language-quick-pick-service.js +6 -4
- package/lib/browser/i18n/language-quick-pick-service.js.map +1 -1
- package/lib/browser/shell/application-shell.d.ts +4 -0
- package/lib/browser/shell/application-shell.d.ts.map +1 -1
- package/lib/browser/shell/application-shell.js +9 -0
- package/lib/browser/shell/application-shell.js.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.d.ts +7 -2
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.d.ts.map +1 -1
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.js +33 -6
- package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.js.map +1 -1
- package/lib/browser/tree/search-box.js +1 -1
- package/lib/browser/tree/search-box.js.map +1 -1
- package/lib/common/encoding-service.d.ts +1 -0
- package/lib/common/encoding-service.d.ts.map +1 -1
- package/lib/common/severity.d.ts +1 -0
- package/lib/common/severity.d.ts.map +1 -1
- package/lib/common/severity.js +24 -5
- package/lib/common/severity.js.map +1 -1
- package/lib/electron-main/electron-main-application.d.ts.map +1 -1
- package/lib/electron-main/electron-main-application.js +3 -1
- package/lib/electron-main/electron-main-application.js.map +1 -1
- package/package.json +6 -6
- package/src/browser/common-frontend-contribution.ts +18 -9
- package/src/browser/core-preferences.ts +9 -11
- package/src/browser/dialogs.ts +72 -0
- package/src/browser/i18n/language-quick-pick-service.ts +8 -7
- package/src/browser/shell/application-shell.ts +13 -0
- package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar.tsx +39 -6
- package/src/browser/style/select-component.css +2 -3
- package/src/browser/style/sidepanel.css +1 -0
- package/src/browser/style/tree.css +2 -0
- package/src/browser/tree/search-box.ts +1 -1
- package/src/common/i18n/nls.metadata.json +14163 -13306
- package/src/common/severity.ts +21 -6
- package/src/electron-main/electron-main-application.ts +3 -1
package/src/browser/dialogs.ts
CHANGED
|
@@ -401,6 +401,78 @@ export async function confirmExit(): Promise<boolean> {
|
|
|
401
401
|
return safeToExit === true;
|
|
402
402
|
}
|
|
403
403
|
|
|
404
|
+
export class ConfirmSaveDialogProps extends ConfirmDialogProps {
|
|
405
|
+
readonly save: string;
|
|
406
|
+
performSave: () => Promise<void>;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
export class ConfirmSaveDialog extends ConfirmDialog {
|
|
410
|
+
|
|
411
|
+
protected saveButton: HTMLButtonElement | undefined;
|
|
412
|
+
constructor(
|
|
413
|
+
@inject(ConfirmSaveDialogProps) protected override readonly props: ConfirmSaveDialogProps
|
|
414
|
+
) {
|
|
415
|
+
super(props);
|
|
416
|
+
this.contentNode.appendChild(this.createMessageNode(this.props.msg));
|
|
417
|
+
// reorder buttons
|
|
418
|
+
this.controlPanel.childNodes.forEach(child => this.controlPanel.removeChild(child));
|
|
419
|
+
[this.acceptButton, this.closeButton].forEach(child => {
|
|
420
|
+
if (typeof child !== 'undefined') {
|
|
421
|
+
this.controlPanel.appendChild(child);
|
|
422
|
+
}
|
|
423
|
+
});
|
|
424
|
+
this.appendSaveButton(props.save).addEventListener('click', async () => {
|
|
425
|
+
await props.performSave();
|
|
426
|
+
this.acceptButton?.click();
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
protected appendSaveButton(text: string = Dialog.OK): HTMLButtonElement {
|
|
431
|
+
this.saveButton = this.createButton(text);
|
|
432
|
+
this.controlPanel.appendChild(this.saveButton);
|
|
433
|
+
this.saveButton.classList.add('main');
|
|
434
|
+
return this.saveButton;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
protected override onActivateRequest(msg: Message): void {
|
|
438
|
+
super.onActivateRequest(msg);
|
|
439
|
+
if (this.saveButton) {
|
|
440
|
+
this.saveButton.focus();
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
export async function confirmExitWithOrWithoutSaving(captionsToSave: string[], performSave: () => Promise<void>): Promise<boolean> {
|
|
447
|
+
const div: HTMLElement = document.createElement('div');
|
|
448
|
+
div.innerText = nls.localizeByDefault("Your changes will be lost if you don't save them.");
|
|
449
|
+
|
|
450
|
+
if (captionsToSave.length > 0) {
|
|
451
|
+
const span = document.createElement('span');
|
|
452
|
+
span.appendChild(document.createElement('br'));
|
|
453
|
+
captionsToSave.forEach(cap => {
|
|
454
|
+
const b = document.createElement('b');
|
|
455
|
+
b.innerText = cap;
|
|
456
|
+
span.appendChild(b);
|
|
457
|
+
span.appendChild(document.createElement('br'));
|
|
458
|
+
});
|
|
459
|
+
span.appendChild(document.createElement('br'));
|
|
460
|
+
div.appendChild(span);
|
|
461
|
+
const safeToExit = await new ConfirmSaveDialog({
|
|
462
|
+
title: nls.localizeByDefault('Do you want to save the changes to the following {0} files?', captionsToSave.length),
|
|
463
|
+
msg: div,
|
|
464
|
+
ok: nls.localizeByDefault("Don't Save"),
|
|
465
|
+
save: nls.localizeByDefault('Save All'),
|
|
466
|
+
cancel: Dialog.CANCEL,
|
|
467
|
+
performSave: performSave
|
|
468
|
+
}).open();
|
|
469
|
+
return safeToExit === true;
|
|
470
|
+
} else {
|
|
471
|
+
// fallback if not passed with an empty caption-list.
|
|
472
|
+
return confirmExit();
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
}
|
|
404
476
|
@injectable()
|
|
405
477
|
export class SingleTextInputDialogProps extends DialogProps {
|
|
406
478
|
readonly confirmButtonLabel?: string;
|
|
@@ -20,8 +20,7 @@ import { AsyncLocalizationProvider, LanguageInfo } from '../../common/i18n/local
|
|
|
20
20
|
import { QuickInputService, QuickPickItem, QuickPickSeparator } from '../quick-input';
|
|
21
21
|
import { WindowService } from '../window/window-service';
|
|
22
22
|
|
|
23
|
-
export interface LanguageQuickPickItem extends QuickPickItem {
|
|
24
|
-
languageId: string
|
|
23
|
+
export interface LanguageQuickPickItem extends QuickPickItem, LanguageInfo {
|
|
25
24
|
execute?(): Promise<void>
|
|
26
25
|
}
|
|
27
26
|
|
|
@@ -32,13 +31,13 @@ export class LanguageQuickPickService {
|
|
|
32
31
|
@inject(AsyncLocalizationProvider) protected readonly localizationProvider: AsyncLocalizationProvider;
|
|
33
32
|
@inject(WindowService) protected readonly windowService: WindowService;
|
|
34
33
|
|
|
35
|
-
async pickDisplayLanguage(): Promise<
|
|
34
|
+
async pickDisplayLanguage(): Promise<LanguageInfo | undefined> {
|
|
36
35
|
const quickInput = this.quickInputService.createQuickPick<LanguageQuickPickItem>();
|
|
37
36
|
const installedItems = await this.getInstalledLanguages();
|
|
38
37
|
const quickInputItems: (LanguageQuickPickItem | QuickPickSeparator)[] = [
|
|
39
38
|
{
|
|
40
39
|
type: 'separator',
|
|
41
|
-
label: nls.localizeByDefault('Installed
|
|
40
|
+
label: nls.localizeByDefault('Installed')
|
|
42
41
|
},
|
|
43
42
|
...installedItems
|
|
44
43
|
];
|
|
@@ -55,7 +54,7 @@ export class LanguageQuickPickService {
|
|
|
55
54
|
if (availableItems.length > 0) {
|
|
56
55
|
quickInputItems.push({
|
|
57
56
|
type: 'separator',
|
|
58
|
-
label: nls.localizeByDefault('Available
|
|
57
|
+
label: nls.localizeByDefault('Available')
|
|
59
58
|
});
|
|
60
59
|
const installed = new Set(installedItems.map(e => e.languageId));
|
|
61
60
|
for (const available of availableItems) {
|
|
@@ -77,7 +76,7 @@ export class LanguageQuickPickService {
|
|
|
77
76
|
// Some language quick pick items want to install additional languages
|
|
78
77
|
// We have to await that before returning the selected locale
|
|
79
78
|
await selectedItem.execute?.();
|
|
80
|
-
resolve(selectedItem
|
|
79
|
+
resolve(selectedItem);
|
|
81
80
|
} else {
|
|
82
81
|
resolve(undefined);
|
|
83
82
|
}
|
|
@@ -122,7 +121,9 @@ export class LanguageQuickPickService {
|
|
|
122
121
|
return {
|
|
123
122
|
label,
|
|
124
123
|
description,
|
|
125
|
-
languageId: id
|
|
124
|
+
languageId: id,
|
|
125
|
+
languageName: language.languageName,
|
|
126
|
+
localizedLanguageName: language.localizedLanguageName
|
|
126
127
|
};
|
|
127
128
|
}
|
|
128
129
|
}
|
|
@@ -89,6 +89,8 @@ export class DockPanelRenderer implements DockLayout.IRenderer {
|
|
|
89
89
|
|
|
90
90
|
readonly tabBarClasses: string[] = [];
|
|
91
91
|
|
|
92
|
+
private readonly onDidCreateTabBarEmitter = new Emitter<TabBar<Widget>>();
|
|
93
|
+
|
|
92
94
|
constructor(
|
|
93
95
|
@inject(TabBarRendererFactory) protected readonly tabBarRendererFactory: TabBarRendererFactory,
|
|
94
96
|
@inject(TabBarToolbarRegistry) protected readonly tabBarToolbarRegistry: TabBarToolbarRegistry,
|
|
@@ -96,6 +98,10 @@ export class DockPanelRenderer implements DockLayout.IRenderer {
|
|
|
96
98
|
@inject(BreadcrumbsRendererFactory) protected readonly breadcrumbsRendererFactory: BreadcrumbsRendererFactory,
|
|
97
99
|
) { }
|
|
98
100
|
|
|
101
|
+
get onDidCreateTabBar(): CommonEvent<TabBar<Widget>> {
|
|
102
|
+
return this.onDidCreateTabBarEmitter.event;
|
|
103
|
+
}
|
|
104
|
+
|
|
99
105
|
createTabBar(): TabBar<Widget> {
|
|
100
106
|
const renderer = this.tabBarRendererFactory();
|
|
101
107
|
const tabBar = new ToolbarAwareTabBar(
|
|
@@ -115,6 +121,7 @@ export class DockPanelRenderer implements DockLayout.IRenderer {
|
|
|
115
121
|
tabBar.disposed.connect(() => renderer.dispose());
|
|
116
122
|
renderer.contextMenuPath = SHELL_TABBAR_CONTEXT_MENU;
|
|
117
123
|
tabBar.currentChanged.connect(this.onCurrentTabChanged, this);
|
|
124
|
+
this.onDidCreateTabBarEmitter.fire(tabBar);
|
|
118
125
|
return tabBar;
|
|
119
126
|
}
|
|
120
127
|
|
|
@@ -221,6 +228,11 @@ export class ApplicationShell extends Widget {
|
|
|
221
228
|
@inject(TheiaDockPanel.Factory)
|
|
222
229
|
protected readonly dockPanelFactory: TheiaDockPanel.Factory;
|
|
223
230
|
|
|
231
|
+
private _mainPanelRenderer: DockPanelRenderer;
|
|
232
|
+
get mainPanelRenderer(): DockPanelRenderer {
|
|
233
|
+
return this._mainPanelRenderer;
|
|
234
|
+
}
|
|
235
|
+
|
|
224
236
|
/**
|
|
225
237
|
* Construct a new application shell.
|
|
226
238
|
*/
|
|
@@ -496,6 +508,7 @@ export class ApplicationShell extends Widget {
|
|
|
496
508
|
const renderer = this.dockPanelRendererFactory();
|
|
497
509
|
renderer.tabBarClasses.push(MAIN_BOTTOM_AREA_CLASS);
|
|
498
510
|
renderer.tabBarClasses.push(MAIN_AREA_CLASS);
|
|
511
|
+
this._mainPanelRenderer = renderer;
|
|
499
512
|
const dockPanel = this.dockPanelFactory({
|
|
500
513
|
mode: 'multiple-document',
|
|
501
514
|
renderer,
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import { inject, injectable } from 'inversify';
|
|
18
18
|
import * as React from 'react';
|
|
19
|
+
import { ContextKeyService } from '../../context-key-service';
|
|
19
20
|
import { CommandRegistry, Disposable, DisposableCollection, MenuCommandExecutor, MenuModelRegistry, MenuPath, nls } from '../../../common';
|
|
20
21
|
import { Anchor, ContextMenuAccess, ContextMenuRenderer } from '../../context-menu-renderer';
|
|
21
22
|
import { LabelIcon, LabelParser } from '../../label-parser';
|
|
@@ -41,12 +42,15 @@ export class TabBarToolbar extends ReactWidget {
|
|
|
41
42
|
protected inline = new Map<string, TabBarToolbarItem | ReactTabBarToolbarItem>();
|
|
42
43
|
protected more = new Map<string, TabBarToolbarItem>();
|
|
43
44
|
|
|
45
|
+
protected contextKeyListener: Disposable | undefined;
|
|
46
|
+
|
|
44
47
|
@inject(CommandRegistry) protected readonly commands: CommandRegistry;
|
|
45
48
|
@inject(LabelParser) protected readonly labelParser: LabelParser;
|
|
46
49
|
@inject(MenuModelRegistry) protected readonly menus: MenuModelRegistry;
|
|
47
50
|
@inject(MenuCommandExecutor) protected readonly menuCommandExecutor: MenuCommandExecutor;
|
|
48
51
|
@inject(ContextMenuRenderer) protected readonly contextMenuRenderer: ContextMenuRenderer;
|
|
49
52
|
@inject(TabBarToolbarRegistry) protected readonly toolbarRegistry: TabBarToolbarRegistry;
|
|
53
|
+
@inject(ContextKeyService) protected readonly contextKeyService: ContextKeyService;
|
|
50
54
|
|
|
51
55
|
constructor() {
|
|
52
56
|
super();
|
|
@@ -60,13 +64,22 @@ export class TabBarToolbar extends ReactWidget {
|
|
|
60
64
|
updateItems(items: Array<TabBarToolbarItem | ReactTabBarToolbarItem>, current: Widget | undefined): void {
|
|
61
65
|
this.inline.clear();
|
|
62
66
|
this.more.clear();
|
|
67
|
+
|
|
68
|
+
const contextKeys = new Set<string>();
|
|
63
69
|
for (const item of items.sort(TabBarToolbarItem.PRIORITY_COMPARATOR).reverse()) {
|
|
64
70
|
if ('render' in item || item.group === undefined || item.group === 'navigation') {
|
|
65
71
|
this.inline.set(item.id, item);
|
|
66
72
|
} else {
|
|
67
73
|
this.more.set(item.id, item);
|
|
68
74
|
}
|
|
75
|
+
|
|
76
|
+
if (item.when) {
|
|
77
|
+
this.contextKeyService.parseKeys(item.when)?.forEach(key => contextKeys.add(key));
|
|
78
|
+
}
|
|
69
79
|
}
|
|
80
|
+
|
|
81
|
+
this.updateContextKeyListener(contextKeys);
|
|
82
|
+
|
|
70
83
|
this.setCurrent(current);
|
|
71
84
|
if (!items.length) {
|
|
72
85
|
this.hide();
|
|
@@ -97,6 +110,17 @@ export class TabBarToolbar extends ReactWidget {
|
|
|
97
110
|
}
|
|
98
111
|
}
|
|
99
112
|
|
|
113
|
+
protected updateContextKeyListener(contextKeys: Set<string>): void {
|
|
114
|
+
this.contextKeyListener?.dispose();
|
|
115
|
+
if (contextKeys.size > 0) {
|
|
116
|
+
this.contextKeyListener = this.contextKeyService.onDidChange(event => {
|
|
117
|
+
if (event.affects(contextKeys)) {
|
|
118
|
+
this.update();
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
100
124
|
protected render(): React.ReactNode {
|
|
101
125
|
return <React.Fragment>
|
|
102
126
|
{this.renderMore()}
|
|
@@ -124,7 +148,8 @@ export class TabBarToolbar extends ReactWidget {
|
|
|
124
148
|
classNames.push(iconClass);
|
|
125
149
|
}
|
|
126
150
|
const tooltip = item.tooltip || (command && command.label);
|
|
127
|
-
|
|
151
|
+
|
|
152
|
+
const toolbarItemClassNames = this.getToolbarItemClassNames(item);
|
|
128
153
|
if (item.menuPath && !item.command) { toolbarItemClassNames.push('enabled'); }
|
|
129
154
|
return <div key={item.id}
|
|
130
155
|
ref={this.onRender}
|
|
@@ -139,13 +164,13 @@ export class TabBarToolbar extends ReactWidget {
|
|
|
139
164
|
</div>;
|
|
140
165
|
}
|
|
141
166
|
|
|
142
|
-
protected getToolbarItemClassNames(
|
|
167
|
+
protected getToolbarItemClassNames(item: AnyToolbarItem): string[] {
|
|
143
168
|
const classNames = [TabBarToolbar.Styles.TAB_BAR_TOOLBAR_ITEM];
|
|
144
|
-
if (
|
|
145
|
-
if (this.commandIsEnabled(
|
|
169
|
+
if (item.command) {
|
|
170
|
+
if (this.commandIsEnabled(item.command) && this.evaluateWhenClause(item.when)) {
|
|
146
171
|
classNames.push('enabled');
|
|
147
172
|
}
|
|
148
|
-
if (this.commandIsToggled(
|
|
173
|
+
if (this.commandIsToggled(item.command)) {
|
|
149
174
|
classNames.push('toggled');
|
|
150
175
|
}
|
|
151
176
|
}
|
|
@@ -221,11 +246,20 @@ export class TabBarToolbar extends ReactWidget {
|
|
|
221
246
|
return this.commands.isToggled(command, this.current);
|
|
222
247
|
}
|
|
223
248
|
|
|
249
|
+
protected evaluateWhenClause(whenClause: string | undefined): boolean {
|
|
250
|
+
return whenClause ? this.contextKeyService.match(whenClause) : true;
|
|
251
|
+
}
|
|
252
|
+
|
|
224
253
|
protected executeCommand = (e: React.MouseEvent<HTMLElement>) => {
|
|
225
254
|
e.preventDefault();
|
|
226
255
|
e.stopPropagation();
|
|
227
256
|
|
|
228
257
|
const item: AnyToolbarItem | undefined = this.inline.get(e.currentTarget.id);
|
|
258
|
+
|
|
259
|
+
if (!this.evaluateWhenClause(item?.when)) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
|
|
229
263
|
if (item?.command && item.menuPath) {
|
|
230
264
|
this.menuCommandExecutor.executeCommand(item.menuPath, item.command, this.current);
|
|
231
265
|
} else if (item?.command) {
|
|
@@ -245,7 +279,6 @@ export class TabBarToolbar extends ReactWidget {
|
|
|
245
279
|
protected onMouseUpEvent = (e: React.MouseEvent<HTMLElement>) => {
|
|
246
280
|
e.currentTarget.classList.remove('active');
|
|
247
281
|
};
|
|
248
|
-
|
|
249
282
|
}
|
|
250
283
|
|
|
251
284
|
export namespace TabBarToolbar {
|
|
@@ -54,7 +54,8 @@
|
|
|
54
54
|
text-overflow: ellipsis;
|
|
55
55
|
overflow: hidden;
|
|
56
56
|
display: flex;
|
|
57
|
-
padding:
|
|
57
|
+
padding: 0px 5px;
|
|
58
|
+
line-height: 22px;
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
.theia-select-component-dropdown .theia-select-component-description {
|
|
@@ -87,8 +88,6 @@
|
|
|
87
88
|
color: var(--theia-list-activeSelectionForeground);
|
|
88
89
|
cursor: pointer;
|
|
89
90
|
background: var(--theia-list-activeSelectionBackground);
|
|
90
|
-
outline: var(--theia-focusBorder) solid 1px;
|
|
91
|
-
outline-offset: -1px;
|
|
92
91
|
}
|
|
93
92
|
|
|
94
93
|
.theia-select-component-dropdown .theia-select-component-separator {
|
|
@@ -100,6 +100,8 @@
|
|
|
100
100
|
.theia-Tree:focus-within .theia-TreeNode.theia-mod-selected {
|
|
101
101
|
background: var(--theia-list-activeSelectionBackground);
|
|
102
102
|
color: var(--theia-list-activeSelectionForeground) !important;
|
|
103
|
+
outline: var(--theia-focusBorder) solid 1px;
|
|
104
|
+
outline-offset: -1px;
|
|
103
105
|
}
|
|
104
106
|
|
|
105
107
|
.theia-Tree:focus-within .theia-TreeNode.theia-mod-selected .theia-TreeNodeTail,
|
|
@@ -254,7 +254,7 @@ export class SearchBox extends BaseWidget {
|
|
|
254
254
|
SearchBox.Styles.BUTTON,
|
|
255
255
|
...SearchBox.Styles.FILTER,
|
|
256
256
|
);
|
|
257
|
-
filter.title = nls.localizeByDefault('
|
|
257
|
+
filter.title = nls.localizeByDefault('Filter on Type');
|
|
258
258
|
buttons.appendChild(filter);
|
|
259
259
|
filter.onclick = this.fireFilterToggle.bind(this);
|
|
260
260
|
}
|