@theia/core 1.47.1 → 1.48.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.
Files changed (111) hide show
  1. package/README.md +6 -6
  2. package/i18n/nls.cs.json +4 -0
  3. package/i18n/nls.de.json +4 -0
  4. package/i18n/nls.es.json +4 -0
  5. package/i18n/nls.fr.json +4 -0
  6. package/i18n/nls.hu.json +4 -0
  7. package/i18n/nls.it.json +4 -0
  8. package/i18n/nls.ja.json +4 -0
  9. package/i18n/nls.json +4 -0
  10. package/i18n/nls.pl.json +4 -0
  11. package/i18n/nls.pt-br.json +4 -0
  12. package/i18n/nls.pt-pt.json +4 -0
  13. package/i18n/nls.ru.json +4 -0
  14. package/i18n/nls.zh-cn.json +4 -0
  15. package/lib/browser/color-application-contribution.d.ts +4 -2
  16. package/lib/browser/color-application-contribution.d.ts.map +1 -1
  17. package/lib/browser/color-application-contribution.js +11 -1
  18. package/lib/browser/color-application-contribution.js.map +1 -1
  19. package/lib/browser/common-frontend-contribution.d.ts +6 -0
  20. package/lib/browser/common-frontend-contribution.d.ts.map +1 -1
  21. package/lib/browser/common-frontend-contribution.js +43 -1
  22. package/lib/browser/common-frontend-contribution.js.map +1 -1
  23. package/lib/browser/decorations-service.js +4 -5
  24. package/lib/browser/decorations-service.js.map +1 -1
  25. package/lib/browser/keybinding.d.ts.map +1 -1
  26. package/lib/browser/keybinding.js +3 -0
  27. package/lib/browser/keybinding.js.map +1 -1
  28. package/lib/browser/menu/browser-context-menu-renderer.d.ts.map +1 -1
  29. package/lib/browser/menu/browser-context-menu-renderer.js +2 -1
  30. package/lib/browser/menu/browser-context-menu-renderer.js.map +1 -1
  31. package/lib/browser/menu/browser-menu-plugin.d.ts +1 -1
  32. package/lib/browser/menu/browser-menu-plugin.d.ts.map +1 -1
  33. package/lib/browser/menu/browser-menu-plugin.js +2 -2
  34. package/lib/browser/menu/browser-menu-plugin.js.map +1 -1
  35. package/lib/browser/secondary-window-handler.d.ts +12 -11
  36. package/lib/browser/secondary-window-handler.d.ts.map +1 -1
  37. package/lib/browser/secondary-window-handler.js +16 -23
  38. package/lib/browser/secondary-window-handler.js.map +1 -1
  39. package/lib/browser/shell/application-shell.d.ts +3 -1
  40. package/lib/browser/shell/application-shell.d.ts.map +1 -1
  41. package/lib/browser/shell/application-shell.js +28 -20
  42. package/lib/browser/shell/application-shell.js.map +1 -1
  43. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.d.ts +1 -0
  44. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.d.ts.map +1 -1
  45. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.js +12 -7
  46. package/lib/browser/shell/tab-bar-toolbar/tab-bar-toolbar.js.map +1 -1
  47. package/lib/browser/styling-service.d.ts +3 -2
  48. package/lib/browser/styling-service.d.ts.map +1 -1
  49. package/lib/browser/styling-service.js +11 -2
  50. package/lib/browser/styling-service.js.map +1 -1
  51. package/lib/browser/window/default-secondary-window-service.d.ts +1 -1
  52. package/lib/browser/window/default-secondary-window-service.d.ts.map +1 -1
  53. package/lib/browser/window/default-secondary-window-service.js +22 -25
  54. package/lib/browser/window/default-secondary-window-service.js.map +1 -1
  55. package/lib/browser/window/default-window-service.d.ts +1 -0
  56. package/lib/browser/window/default-window-service.d.ts.map +1 -1
  57. package/lib/browser/window/default-window-service.js +3 -0
  58. package/lib/browser/window/default-window-service.js.map +1 -1
  59. package/lib/browser/window/test/mock-window-service.d.ts +1 -0
  60. package/lib/browser/window/test/mock-window-service.d.ts.map +1 -1
  61. package/lib/browser/window/test/mock-window-service.js +1 -0
  62. package/lib/browser/window/test/mock-window-service.js.map +1 -1
  63. package/lib/browser/window/window-service.d.ts +10 -2
  64. package/lib/browser/window/window-service.d.ts.map +1 -1
  65. package/lib/browser/window/window-service.js.map +1 -1
  66. package/lib/common/nls.js +3 -1
  67. package/lib/common/nls.js.map +1 -1
  68. package/lib/common/quick-pick-service.d.ts +1 -0
  69. package/lib/common/quick-pick-service.d.ts.map +1 -1
  70. package/lib/common/quick-pick-service.js.map +1 -1
  71. package/lib/electron-browser/menu/electron-context-menu-renderer.d.ts.map +1 -1
  72. package/lib/electron-browser/menu/electron-context-menu-renderer.js +3 -1
  73. package/lib/electron-browser/menu/electron-context-menu-renderer.js.map +1 -1
  74. package/lib/electron-browser/preload.js +2 -2
  75. package/lib/electron-browser/preload.js.map +1 -1
  76. package/lib/electron-browser/window/electron-secondary-window-service.d.ts +1 -1
  77. package/lib/electron-browser/window/electron-secondary-window-service.d.ts.map +1 -1
  78. package/lib/electron-browser/window/electron-secondary-window-service.js +4 -8
  79. package/lib/electron-browser/window/electron-secondary-window-service.js.map +1 -1
  80. package/lib/electron-browser/window/electron-window-service.d.ts +3 -1
  81. package/lib/electron-browser/window/electron-window-service.d.ts.map +1 -1
  82. package/lib/electron-browser/window/electron-window-service.js +12 -2
  83. package/lib/electron-browser/window/electron-window-service.js.map +1 -1
  84. package/lib/electron-common/electron-api.d.ts +1 -1
  85. package/lib/electron-common/electron-api.d.ts.map +1 -1
  86. package/lib/electron-main/electron-api-main.d.ts.map +1 -1
  87. package/lib/electron-main/electron-api-main.js +9 -1
  88. package/lib/electron-main/electron-api-main.js.map +1 -1
  89. package/package.json +6 -6
  90. package/src/browser/color-application-contribution.ts +11 -2
  91. package/src/browser/common-frontend-contribution.ts +44 -1
  92. package/src/browser/decorations-service.ts +4 -4
  93. package/src/browser/keybinding.ts +3 -0
  94. package/src/browser/menu/browser-context-menu-renderer.ts +2 -1
  95. package/src/browser/menu/browser-menu-plugin.ts +2 -2
  96. package/src/browser/secondary-window-handler.ts +21 -22
  97. package/src/browser/shell/application-shell.ts +25 -18
  98. package/src/browser/shell/tab-bar-toolbar/tab-bar-toolbar.tsx +15 -10
  99. package/src/browser/styling-service.ts +12 -3
  100. package/src/browser/window/default-secondary-window-service.ts +24 -26
  101. package/src/browser/window/default-window-service.ts +4 -0
  102. package/src/browser/window/test/mock-window-service.ts +1 -0
  103. package/src/browser/window/window-service.ts +12 -2
  104. package/src/common/nls.ts +3 -1
  105. package/src/common/quick-pick-service.ts +1 -0
  106. package/src/electron-browser/menu/electron-context-menu-renderer.ts +3 -1
  107. package/src/electron-browser/preload.ts +2 -2
  108. package/src/electron-browser/window/electron-secondary-window-service.ts +4 -8
  109. package/src/electron-browser/window/electron-window-service.ts +15 -3
  110. package/src/electron-common/electron-api.ts +1 -1
  111. package/src/electron-main/electron-api-main.ts +8 -1
@@ -82,37 +82,14 @@ export class DefaultSecondaryWindowService implements SecondaryWindowService {
82
82
  }
83
83
 
84
84
  createSecondaryWindow(widget: ExtractableWidget, shell: ApplicationShell): Window | undefined {
85
- const win = this.doCreateSecondaryWindow(widget, shell);
86
- if (win) {
87
- this.secondaryWindows.push(win);
88
- win.addEventListener('close', () => {
89
- const extIndex = this.secondaryWindows.indexOf(win);
90
- if (extIndex > -1) {
91
- this.secondaryWindows.splice(extIndex, 1);
92
- };
93
- });
94
- }
95
- return win;
96
- }
97
-
98
- protected findWindow<T>(windowName: string): Window | undefined {
99
- for (const w of this.secondaryWindows) {
100
- if (w.name === windowName) {
101
- return w;
102
- }
103
- }
104
- return undefined;
105
- }
106
-
107
- protected doCreateSecondaryWindow(widget: ExtractableWidget, shell: ApplicationShell): Window | undefined {
108
- let options;
109
85
  const [height, width, left, top] = this.findSecondaryWindowCoordinates(widget);
110
- options = `popup=1,width=${width},height=${height},left=${left},top=${top}`;
86
+ let options = `popup=1,width=${width},height=${height},left=${left},top=${top}`;
111
87
  if (this.preferenceService.get('window.secondaryWindowAlwaysOnTop')) {
112
88
  options += ',alwaysOnTop=true';
113
89
  }
114
90
  const newWindow = window.open(DefaultSecondaryWindowService.SECONDARY_WINDOW_URL, this.nextWindowId(), options) ?? undefined;
115
91
  if (newWindow) {
92
+ this.secondaryWindows.push(newWindow);
116
93
  newWindow.addEventListener('DOMContentLoaded', () => {
117
94
  newWindow.addEventListener('beforeunload', evt => {
118
95
  const saveable = Saveable.get(widget);
@@ -124,17 +101,38 @@ export class DefaultSecondaryWindowService implements SecondaryWindowService {
124
101
  }
125
102
  }, { capture: true });
126
103
 
127
- newWindow.addEventListener('close', () => {
104
+ newWindow.addEventListener('unload', () => {
128
105
  const saveable = Saveable.get(widget);
129
106
  shell.closeWidget(widget.id, {
130
107
  save: !!saveable && saveable.dirty && saveable.autoSave !== 'off'
131
108
  });
109
+
110
+ const extIndex = this.secondaryWindows.indexOf(newWindow);
111
+ if (extIndex > -1) {
112
+ this.secondaryWindows.splice(extIndex, 1);
113
+ };
132
114
  });
115
+ this.windowCreated(newWindow, widget, shell);
133
116
  });
134
117
  }
135
118
  return newWindow;
136
119
  }
137
120
 
121
+ protected windowCreated(newWindow: Window, widget: ExtractableWidget, shell: ApplicationShell): void {
122
+ newWindow.addEventListener('unload', () => {
123
+ shell.closeWidget(widget.id);
124
+ });
125
+ }
126
+
127
+ protected findWindow<T>(windowName: string): Window | undefined {
128
+ for (const w of this.secondaryWindows) {
129
+ if (w.name === windowName) {
130
+ return w;
131
+ }
132
+ }
133
+ return undefined;
134
+ }
135
+
138
136
  protected findSecondaryWindowCoordinates(widget: ExtractableWidget): (number | undefined)[] {
139
137
  const clientBounds = widget.node.getBoundingClientRect();
140
138
  const preference = this.preferenceService.get('window.secondaryWindowPlacement');
@@ -57,6 +57,10 @@ export class DefaultWindowService implements WindowService, FrontendApplicationC
57
57
  this.openNewWindow(`#${DEFAULT_WINDOW_HASH}`);
58
58
  }
59
59
 
60
+ focus(): void {
61
+ window.focus();
62
+ }
63
+
60
64
  /**
61
65
  * Returns a list of actions that {@link FrontendApplicationContribution}s would like to take before shutdown
62
66
  * It is expected that this will succeed - i.e. return an empty array - at most once per session. If no vetoes are received
@@ -21,6 +21,7 @@ import { WindowService } from '../window-service';
21
21
  export class MockWindowService implements WindowService {
22
22
  openNewWindow(): undefined { return undefined; }
23
23
  openNewDefaultWindow(): void { }
24
+ focus(): void { }
24
25
  reload(): void { }
25
26
  isSafeToShutDown(): Promise<boolean> { return Promise.resolve(true); }
26
27
  setSafeToShutDown(): void { }
@@ -18,6 +18,11 @@ import { StopReason } from '../../common/frontend-application-state';
18
18
  import { Event } from '../../common/event';
19
19
  import { NewWindowOptions, WindowSearchParams } from '../../common/window';
20
20
 
21
+ export interface WindowReloadOptions {
22
+ search?: WindowSearchParams,
23
+ hash?: string
24
+ }
25
+
21
26
  /**
22
27
  * Service for opening new browser windows.
23
28
  */
@@ -35,7 +40,12 @@ export interface WindowService {
35
40
  * Opens a new default window.
36
41
  * - In electron and in the browser it will open the default window without a pre-defined content.
37
42
  */
38
- openNewDefaultWindow(params?: WindowSearchParams): void;
43
+ openNewDefaultWindow(params?: WindowReloadOptions): void;
44
+
45
+ /**
46
+ * Reveal and focuses the current window
47
+ */
48
+ focus(): void;
39
49
 
40
50
  /**
41
51
  * Fires when the `window` unloads. The unload event is inevitable. On this event, the frontend application can save its state and release resource.
@@ -64,5 +74,5 @@ export interface WindowService {
64
74
  /**
65
75
  * Reloads the window according to platform.
66
76
  */
67
- reload(params?: WindowSearchParams): void;
77
+ reload(params?: WindowReloadOptions): void;
68
78
  }
package/src/common/nls.ts CHANGED
@@ -83,7 +83,9 @@ class LocalizationKeyProvider {
83
83
 
84
84
  private preferredKeys = new Set([
85
85
  // We only want the `File` translation used in the menu
86
- 'vscode/fileActions.contribution/filesCategory'
86
+ 'vscode/fileActions.contribution/filesCategory',
87
+ // Needed for `Close Editor` translation
88
+ 'vscode/editor.contribution/closeEditor'
87
89
  ]);
88
90
  private data = this.buildData();
89
91
 
@@ -161,6 +161,7 @@ export interface QuickPick<T extends QuickPickItemOrSeparator> extends QuickInpu
161
161
  matchOnDescription: boolean;
162
162
  matchOnDetail: boolean;
163
163
  keepScrollPosition: boolean;
164
+ buttons: ReadonlyArray<QuickInputButton>;
164
165
  readonly onDidAccept: Event<{ inBackground: boolean } | undefined>;
165
166
  readonly onDidChangeValue: Event<string>;
166
167
  readonly onDidTriggerButton: Event<QuickInputButton>;
@@ -104,11 +104,13 @@ export class ElectronContextMenuRenderer extends BrowserContextMenuRenderer {
104
104
  const menu = this.electronMenuFactory.createElectronContextMenu(menuPath, args, context, contextKeyService, skipSingleRootNode);
105
105
  const { x, y } = coordinateFromAnchor(anchor);
106
106
 
107
+ const windowName = options.context?.ownerDocument.defaultView?.Window.name;
108
+
107
109
  const menuHandle = window.electronTheiaCore.popup(menu, x, y, () => {
108
110
  if (onHide) {
109
111
  onHide();
110
112
  }
111
- });
113
+ }, windowName);
112
114
  // native context menu stops the event loop, so there is no keyboard events
113
115
  this.context.resetAltPressed();
114
116
  return new ElectronContextMenuAccess(menuHandle);
@@ -81,11 +81,11 @@ const api: TheiaCoreAPI = {
81
81
  },
82
82
  attachSecurityToken: (endpoint: string) => ipcRenderer.invoke(CHANNEL_ATTACH_SECURITY_TOKEN, endpoint),
83
83
 
84
- popup: async function (menu: MenuDto[], x: number, y: number, onClosed: () => void): Promise<number> {
84
+ popup: async function (menu: MenuDto[], x: number, y: number, onClosed: () => void, windowName?: string): Promise<number> {
85
85
  const menuId = nextMenuId++;
86
86
  const handlers = new Map<number, () => void>();
87
87
  commandHandlers.set(menuId, handlers);
88
- const handle = await ipcRenderer.invoke(CHANNEL_OPEN_POPUP, menuId, convertMenu(menu, handlers), x, y);
88
+ const handle = await ipcRenderer.invoke(CHANNEL_OPEN_POPUP, menuId, convertMenu(menu, handlers), x, y, windowName);
89
89
  const closeListener = () => {
90
90
  ipcRenderer.removeListener(CHANNEL_ON_CLOSE_POPUP, closeListener);
91
91
  commandHandlers.delete(menuId);
@@ -24,16 +24,12 @@ export class ElectronSecondaryWindowService extends DefaultSecondaryWindowServic
24
24
  window.electronTheiaCore.focusWindow(win.name);
25
25
  }
26
26
 
27
- protected override doCreateSecondaryWindow(widget: ExtractableWidget, shell: ApplicationShell): Window | undefined {
28
- const w = super.doCreateSecondaryWindow(widget, shell);
29
- if (w) {
30
- window.electronTheiaCore.setMenuBarVisible(false, w.name);
31
- window.electronTheiaCore.setSecondaryWindowCloseRequestHandler(w.name, () => this.canClose(widget, shell));
32
- }
33
- return w;
27
+ protected override windowCreated(newWindow: Window, widget: ExtractableWidget, shell: ApplicationShell): void {
28
+ window.electronTheiaCore.setMenuBarVisible(false, newWindow.name);
29
+ window.electronTheiaCore.setSecondaryWindowCloseRequestHandler(newWindow.name, () => this.canClose(widget, shell));
34
30
  }
35
31
  private async canClose(widget: ExtractableWidget, shell: ApplicationShell): Promise<boolean> {
36
- await shell.closeWidget(widget.id, undefined);
32
+ await shell.closeWidget(widget.id);
37
33
  return widget.isDisposed;
38
34
  }
39
35
  }
@@ -21,6 +21,7 @@ import { ElectronMainWindowService } from '../../electron-common/electron-main-w
21
21
  import { ElectronWindowPreferences } from './electron-window-preferences';
22
22
  import { ConnectionCloseService } from '../../common/messaging/connection-management';
23
23
  import { FrontendIdProvider } from '../../browser/messaging/frontend-id-provider';
24
+ import { WindowReloadOptions } from '../../browser/window/window-service';
24
25
 
25
26
  @injectable()
26
27
  export class ElectronWindowService extends DefaultWindowService {
@@ -56,6 +57,9 @@ export class ElectronWindowService extends DefaultWindowService {
56
57
  this.delegate.openNewDefaultWindow(params);
57
58
  }
58
59
 
60
+ override focus(): void {
61
+ window.electronTheiaCore.focusWindow(window.name);
62
+ }
59
63
  @postConstruct()
60
64
  protected init(): void {
61
65
  // Update the default zoom level on startup when the preferences event is fired.
@@ -86,12 +90,20 @@ export class ElectronWindowService extends DefaultWindowService {
86
90
  }
87
91
  }
88
92
 
89
- override reload(params?: WindowSearchParams): void {
93
+ override reload(params?: WindowReloadOptions): void {
90
94
  if (params) {
91
- const query = Object.entries(params).map(([name, value]) => `${name}=${value}`).join('&');
92
- location.search = query;
95
+ const newLocation = new URL(location.href);
96
+ if (params.search) {
97
+ const query = Object.entries(params.search).map(([name, value]) => `${name}=${value}`).join('&');
98
+ newLocation.search = query;
99
+ }
100
+ if (params.hash) {
101
+ newLocation.hash = '#' + params.hash;
102
+ }
103
+ location.assign(newLocation);
93
104
  } else {
94
105
  window.electronTheiaCore.requestReload();
95
106
  }
96
107
  }
97
108
  }
109
+
@@ -50,7 +50,7 @@ export interface TheiaCoreAPI {
50
50
  setMenuBarVisible(visible: boolean, windowName?: string): void;
51
51
  setMenu(menu: MenuDto[] | undefined): void;
52
52
 
53
- popup(menu: MenuDto[], x: number, y: number, onClosed: () => void): Promise<number>;
53
+ popup(menu: MenuDto[], x: number, y: number, onClosed: () => void, windowName?: string): Promise<number>;
54
54
  closePopup(handle: number): void;
55
55
 
56
56
  focusWindow(name: string): void;
@@ -115,7 +115,7 @@ export class TheiaMainApi implements ElectronMainApplicationContribution {
115
115
  });
116
116
 
117
117
  // popup menu
118
- ipcMain.handle(CHANNEL_OPEN_POPUP, (event, menuId, menu, x, y) => {
118
+ ipcMain.handle(CHANNEL_OPEN_POPUP, (event, menuId, menu, x, y, windowName?: string) => {
119
119
  const zoom = event.sender.getZoomFactor();
120
120
  // TODO: Remove the offset once Electron fixes https://github.com/electron/electron/issues/31641
121
121
  const offset = process.platform === 'win32' ? 0 : 2;
@@ -124,7 +124,14 @@ export class TheiaMainApi implements ElectronMainApplicationContribution {
124
124
  y = Math.round(y * zoom) + offset;
125
125
  const popup = Menu.buildFromTemplate(this.fromMenuDto(event.sender, menuId, menu));
126
126
  this.openPopups.set(menuId, popup);
127
+ let electronWindow: BrowserWindow | undefined;
128
+ if (windowName) {
129
+ electronWindow = BrowserWindow.getAllWindows().find(win => win.webContents.mainFrame.name === windowName);
130
+ } else {
131
+ electronWindow = BrowserWindow.fromWebContents(event.sender) || undefined;
132
+ }
127
133
  popup.popup({
134
+ window: electronWindow,
128
135
  callback: () => {
129
136
  this.openPopups.delete(menuId);
130
137
  event.sender.send(CHANNEL_ON_CLOSE_POPUP, menuId);