@theia/plugin-ext 1.37.0-next.3 → 1.37.0-next.30

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 (156) hide show
  1. package/lib/common/language-pack-service.d.ts +16 -0
  2. package/lib/common/language-pack-service.d.ts.map +1 -0
  3. package/lib/common/language-pack-service.js +21 -0
  4. package/lib/common/language-pack-service.js.map +1 -0
  5. package/lib/common/plugin-api-rpc-model.d.ts +6 -0
  6. package/lib/common/plugin-api-rpc-model.d.ts.map +1 -1
  7. package/lib/common/plugin-api-rpc-model.js +6 -1
  8. package/lib/common/plugin-api-rpc-model.js.map +1 -1
  9. package/lib/common/plugin-api-rpc.d.ts +22 -1
  10. package/lib/common/plugin-api-rpc.d.ts.map +1 -1
  11. package/lib/common/plugin-api-rpc.js +2 -1
  12. package/lib/common/plugin-api-rpc.js.map +1 -1
  13. package/lib/common/plugin-protocol.d.ts +2 -0
  14. package/lib/common/plugin-protocol.d.ts.map +1 -1
  15. package/lib/common/plugin-protocol.js.map +1 -1
  16. package/lib/hosted/browser/hosted-plugin.d.ts +6 -2
  17. package/lib/hosted/browser/hosted-plugin.d.ts.map +1 -1
  18. package/lib/hosted/browser/hosted-plugin.js +26 -5
  19. package/lib/hosted/browser/hosted-plugin.js.map +1 -1
  20. package/lib/hosted/browser/worker/worker-main.js +4 -2
  21. package/lib/hosted/browser/worker/worker-main.js.map +1 -1
  22. package/lib/hosted/node/hosted-plugin-deployer-handler.js +2 -2
  23. package/lib/hosted/node/hosted-plugin-deployer-handler.js.map +1 -1
  24. package/lib/hosted/node/hosted-plugin-localization-service.d.ts +13 -1
  25. package/lib/hosted/node/hosted-plugin-localization-service.d.ts.map +1 -1
  26. package/lib/hosted/node/hosted-plugin-localization-service.js +122 -10
  27. package/lib/hosted/node/hosted-plugin-localization-service.js.map +1 -1
  28. package/lib/hosted/node/plugin-ext-hosted-backend-module.d.ts.map +1 -1
  29. package/lib/hosted/node/plugin-ext-hosted-backend-module.js +7 -0
  30. package/lib/hosted/node/plugin-ext-hosted-backend-module.js.map +1 -1
  31. package/lib/hosted/node/plugin-host-rpc.d.ts +2 -2
  32. package/lib/hosted/node/plugin-host-rpc.d.ts.map +1 -1
  33. package/lib/hosted/node/plugin-host-rpc.js +6 -4
  34. package/lib/hosted/node/plugin-host-rpc.js.map +1 -1
  35. package/lib/hosted/node/plugin-language-pack-service.d.ts +8 -0
  36. package/lib/hosted/node/plugin-language-pack-service.d.ts.map +1 -0
  37. package/lib/hosted/node/plugin-language-pack-service.js +54 -0
  38. package/lib/hosted/node/plugin-language-pack-service.js.map +1 -0
  39. package/lib/hosted/node/scanners/scanner-theia.d.ts.map +1 -1
  40. package/lib/hosted/node/scanners/scanner-theia.js +1 -0
  41. package/lib/hosted/node/scanners/scanner-theia.js.map +1 -1
  42. package/lib/main/browser/comments/comment-thread-widget.d.ts.map +1 -1
  43. package/lib/main/browser/comments/comment-thread-widget.js +5 -1
  44. package/lib/main/browser/comments/comment-thread-widget.js.map +1 -1
  45. package/lib/main/browser/comments/comments-main.d.ts +6 -1
  46. package/lib/main/browser/comments/comments-main.d.ts.map +1 -1
  47. package/lib/main/browser/comments/comments-main.js +15 -0
  48. package/lib/main/browser/comments/comments-main.js.map +1 -1
  49. package/lib/main/browser/localization-main.d.ts +9 -0
  50. package/lib/main/browser/localization-main.d.ts.map +1 -0
  51. package/lib/main/browser/localization-main.js +32 -0
  52. package/lib/main/browser/localization-main.js.map +1 -0
  53. package/lib/main/browser/main-context.d.ts.map +1 -1
  54. package/lib/main/browser/main-context.js +3 -0
  55. package/lib/main/browser/main-context.js.map +1 -1
  56. package/lib/main/browser/plugin-ext-frontend-module.d.ts.map +1 -1
  57. package/lib/main/browser/plugin-ext-frontend-module.js +5 -0
  58. package/lib/main/browser/plugin-ext-frontend-module.js.map +1 -1
  59. package/lib/main/browser/view/plugin-view-registry.js +1 -1
  60. package/lib/main/browser/view/plugin-view-registry.js.map +1 -1
  61. package/lib/main/browser/view/tree-view-widget.d.ts.map +1 -1
  62. package/lib/main/browser/view/tree-view-widget.js +10 -1
  63. package/lib/main/browser/view/tree-view-widget.js.map +1 -1
  64. package/lib/main/electron-browser/webview/electron-webview-widget-factory.d.ts +1 -0
  65. package/lib/main/electron-browser/webview/electron-webview-widget-factory.d.ts.map +1 -1
  66. package/lib/main/electron-browser/webview/electron-webview-widget-factory.js +4 -15
  67. package/lib/main/electron-browser/webview/electron-webview-widget-factory.js.map +1 -1
  68. package/lib/main/node/plugin-github-resolver.d.ts +3 -1
  69. package/lib/main/node/plugin-github-resolver.d.ts.map +1 -1
  70. package/lib/main/node/plugin-github-resolver.js +64 -71
  71. package/lib/main/node/plugin-github-resolver.js.map +1 -1
  72. package/lib/main/node/plugin-http-resolver.d.ts +2 -0
  73. package/lib/main/node/plugin-http-resolver.d.ts.map +1 -1
  74. package/lib/main/node/plugin-http-resolver.js +31 -31
  75. package/lib/main/node/plugin-http-resolver.js.map +1 -1
  76. package/lib/main/node/plugins-key-value-storage.js +1 -1
  77. package/lib/main/node/plugins-key-value-storage.js.map +1 -1
  78. package/lib/plugin/comments.d.ts +3 -0
  79. package/lib/plugin/comments.d.ts.map +1 -1
  80. package/lib/plugin/comments.js +24 -0
  81. package/lib/plugin/comments.js.map +1 -1
  82. package/lib/plugin/localization-ext.d.ts +17 -0
  83. package/lib/plugin/localization-ext.d.ts.map +1 -0
  84. package/lib/plugin/localization-ext.js +74 -0
  85. package/lib/plugin/localization-ext.js.map +1 -0
  86. package/lib/plugin/output-channel/log-output-channel.d.ts +24 -0
  87. package/lib/plugin/output-channel/log-output-channel.d.ts.map +1 -0
  88. package/lib/plugin/output-channel/log-output-channel.js +92 -0
  89. package/lib/plugin/output-channel/log-output-channel.js.map +1 -0
  90. package/lib/plugin/output-channel/output-channel-item.d.ts +3 -3
  91. package/lib/plugin/output-channel/output-channel-item.d.ts.map +1 -1
  92. package/lib/plugin/output-channel/output-channel-item.js.map +1 -1
  93. package/lib/plugin/output-channel-registry.d.ts +7 -2
  94. package/lib/plugin/output-channel-registry.d.ts.map +1 -1
  95. package/lib/plugin/output-channel-registry.js +15 -6
  96. package/lib/plugin/output-channel-registry.js.map +1 -1
  97. package/lib/plugin/plugin-context.d.ts +2 -1
  98. package/lib/plugin/plugin-context.d.ts.map +1 -1
  99. package/lib/plugin/plugin-context.js +26 -3
  100. package/lib/plugin/plugin-context.js.map +1 -1
  101. package/lib/plugin/plugin-manager.d.ts +3 -2
  102. package/lib/plugin/plugin-manager.d.ts.map +1 -1
  103. package/lib/plugin/plugin-manager.js +4 -1
  104. package/lib/plugin/plugin-manager.js.map +1 -1
  105. package/lib/plugin/stubs/tests-api.d.ts +2 -1
  106. package/lib/plugin/stubs/tests-api.d.ts.map +1 -1
  107. package/lib/plugin/stubs/tests-api.js +2 -1
  108. package/lib/plugin/stubs/tests-api.js.map +1 -1
  109. package/lib/plugin/tree/tree-views.d.ts +2 -0
  110. package/lib/plugin/tree/tree-views.d.ts.map +1 -1
  111. package/lib/plugin/tree/tree-views.js +10 -3
  112. package/lib/plugin/tree/tree-views.js.map +1 -1
  113. package/lib/plugin/type-converters.d.ts.map +1 -1
  114. package/lib/plugin/type-converters.js +6 -3
  115. package/lib/plugin/type-converters.js.map +1 -1
  116. package/lib/plugin/types-impl.d.ts +8 -4
  117. package/lib/plugin/types-impl.d.ts.map +1 -1
  118. package/lib/plugin/types-impl.js +12 -7
  119. package/lib/plugin/types-impl.js.map +1 -1
  120. package/package.json +27 -29
  121. package/src/common/language-pack-service.ts +34 -0
  122. package/src/common/plugin-api-rpc-model.ts +7 -0
  123. package/src/common/plugin-api-rpc.ts +25 -2
  124. package/src/common/plugin-protocol.ts +2 -0
  125. package/src/hosted/browser/hosted-plugin.ts +27 -6
  126. package/src/hosted/browser/worker/worker-main.ts +5 -2
  127. package/src/hosted/node/hosted-plugin-deployer-handler.ts +2 -2
  128. package/src/hosted/node/hosted-plugin-localization-service.ts +132 -11
  129. package/src/hosted/node/plugin-ext-hosted-backend-module.ts +12 -0
  130. package/src/hosted/node/plugin-host-rpc.ts +8 -5
  131. package/src/hosted/node/plugin-language-pack-service.ts +43 -0
  132. package/src/hosted/node/scanners/scanner-theia.ts +1 -0
  133. package/src/main/browser/comments/comment-thread-widget.tsx +6 -1
  134. package/src/main/browser/comments/comments-main.ts +18 -1
  135. package/src/main/browser/localization-main.ts +34 -0
  136. package/src/main/browser/main-context.ts +4 -0
  137. package/src/main/browser/plugin-ext-frontend-module.ts +6 -0
  138. package/src/main/browser/view/plugin-view-registry.ts +1 -1
  139. package/src/main/browser/view/tree-view-widget.tsx +11 -1
  140. package/src/main/electron-browser/webview/electron-webview-widget-factory.ts +4 -15
  141. package/src/main/node/plugin-github-resolver.ts +65 -81
  142. package/src/main/node/plugin-http-resolver.ts +29 -35
  143. package/src/main/node/plugins-key-value-storage.ts +1 -1
  144. package/src/plugin/comments.ts +32 -1
  145. package/src/plugin/localization-ext.ts +84 -0
  146. package/src/plugin/output-channel/log-output-channel.ts +108 -0
  147. package/src/plugin/output-channel/output-channel-item.ts +2 -2
  148. package/src/plugin/output-channel-registry.ts +20 -7
  149. package/src/plugin/plugin-context.ts +31 -3
  150. package/src/plugin/plugin-manager.ts +5 -1
  151. package/src/plugin/stubs/tests-api.ts +3 -1
  152. package/src/plugin/tree/tree-views.ts +12 -3
  153. package/src/plugin/type-converters.ts +5 -3
  154. package/src/plugin/types-impl.ts +8 -3
  155. package/LICENSE +0 -642
  156. package/src/main/browser/style/test.svg +0 -13
@@ -0,0 +1,34 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2023 TypeFox 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 { nls } from '@theia/core';
18
+ import { interfaces } from '@theia/core/shared/inversify';
19
+ import { LocalizationMain } from '../../common/plugin-api-rpc';
20
+ import { LanguagePackBundle, LanguagePackService } from '../../common/language-pack-service';
21
+
22
+ export class LocalizationMainImpl implements LocalizationMain {
23
+
24
+ private readonly languagePackService: LanguagePackService;
25
+
26
+ constructor(container: interfaces.Container) {
27
+ this.languagePackService = container.get(LanguagePackService);
28
+ }
29
+
30
+ async $fetchBundle(id: string): Promise<LanguagePackBundle | undefined> {
31
+ const bundle = await this.languagePackService.getBundle(id, nls.locale ?? nls.defaultLocale);
32
+ return bundle;
33
+ }
34
+ }
@@ -59,6 +59,7 @@ import { MonacoLanguages } from '@theia/monaco/lib/browser/monaco-languages';
59
59
  import { UntitledResourceResolver } from '@theia/core/lib/common/resource';
60
60
  import { ThemeService } from '@theia/core/lib/browser/theming';
61
61
  import { TabsMainImpl } from './tabs/tabs-main';
62
+ import { LocalizationMainImpl } from './localization-main';
62
63
 
63
64
  export function setUpPluginApi(rpc: RPCProtocol, container: interfaces.Container): void {
64
65
  const authenticationMain = new AuthenticationMainImpl(rpc, container);
@@ -184,4 +185,7 @@ export function setUpPluginApi(rpc: RPCProtocol, container: interfaces.Container
184
185
 
185
186
  const tabsMain = new TabsMainImpl(rpc, container);
186
187
  rpc.set(PLUGIN_RPC_CONTEXT.TABS_MAIN, tabsMain);
188
+
189
+ const localizationMain = new LocalizationMainImpl(container);
190
+ rpc.set(PLUGIN_RPC_CONTEXT.LOCALIZATION_MAIN, localizationMain);
187
191
  }
@@ -83,6 +83,7 @@ import './theme-icon-override';
83
83
  import { PluginTerminalRegistry } from './plugin-terminal-registry';
84
84
  import { DnDFileContentStore } from './view/dnd-file-content-store';
85
85
  import { WebviewContextKeys } from './webview/webview-context-keys';
86
+ import { LanguagePackService, languagePackServicePath } from '../../common/language-pack-service';
86
87
 
87
88
  export default new ContainerModule((bind, unbind, isBound, rebind) => {
88
89
 
@@ -249,4 +250,9 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
249
250
  rebind(AuthenticationService).toService(PluginAuthenticationServiceImpl);
250
251
 
251
252
  bind(PluginTerminalRegistry).toSelf().inSingletonScope();
253
+
254
+ bind(LanguagePackService).toDynamicValue(ctx => {
255
+ const provider = ctx.container.get(WebSocketConnectionProvider);
256
+ return provider.createProxy<LanguagePackService>(languagePackServicePath);
257
+ }).inSingletonScope();
252
258
  });
@@ -158,7 +158,7 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
158
158
  }
159
159
  });
160
160
  this.doRegisterViewContainer('test', 'left', {
161
- label: 'Test',
161
+ label: nls.localizeByDefault('Test'),
162
162
  iconClass: codicon('beaker'),
163
163
  closeable: true
164
164
  });
@@ -632,13 +632,23 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
632
632
 
633
633
  handleDragEnd(node: TreeViewNode, event: React.DragEvent<HTMLElement>): void {
634
634
  this.applicationShell.clearAdditionalDraggedEditorUris();
635
+ this.model.proxy!.$dragEnd(this.id);
635
636
  }
636
637
 
637
638
  handleDragOver(event: React.DragEvent<HTMLElement>): void {
639
+ const hasFiles = (items: DataTransferItemList) => {
640
+ for (let i = 0; i < items.length; i++) {
641
+ if (items[i].kind === 'file') {
642
+ return true;
643
+ }
644
+ }
645
+ return false;
646
+ };
647
+
638
648
  if (event.dataTransfer) {
639
649
  const canDrop = event.dataTransfer.types.some(type => this.options.dropMimeTypes!.includes(type)) ||
640
650
  event.dataTransfer.types.includes(this.treeDragType) ||
641
- this.options.dropMimeTypes!.includes('files') && event.dataTransfer.files.length > 0;
651
+ this.options.dropMimeTypes!.includes('files') && hasFiles(event.dataTransfer.items);
642
652
  if (canDrop) {
643
653
  event.preventDefault();
644
654
  event.dataTransfer.dropEffect = 'move';
@@ -14,12 +14,11 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import * as electronRemote from '@theia/core/electron-shared/@electron/remote';
18
- import { ElectronSecurityToken } from '@theia/core/lib/electron-common/electron-token';
19
17
  import { WebviewWidgetFactory } from '../../browser/webview/webview-widget-factory';
20
18
  import { WebviewWidgetIdentifier, WebviewWidget } from '../../browser/webview/webview';
21
19
  import { CustomEditorWidgetFactory } from '../../browser/custom-editors/custom-editor-widget-factory';
22
20
  import { CustomEditorWidget } from '../../browser/custom-editors/custom-editor-widget';
21
+ import '@theia/core/lib/electron-common/electron-api';
23
22
 
24
23
  export class ElectronWebviewWidgetFactory extends WebviewWidgetFactory {
25
24
 
@@ -34,13 +33,8 @@ export class ElectronWebviewWidgetFactory extends WebviewWidgetFactory {
34
33
  *
35
34
  * @param endpoint cookie's target url
36
35
  */
37
- protected async attachElectronSecurityCookie(endpoint: string): Promise<void> {
38
- await electronRemote.session.defaultSession.cookies.set({
39
- url: endpoint,
40
- name: ElectronSecurityToken,
41
- value: JSON.stringify(this.container.get(ElectronSecurityToken)),
42
- httpOnly: true
43
- });
36
+ protected attachElectronSecurityCookie(endpoint: string): Promise<void> {
37
+ return window.electronTheiaCore.attachSecurityToken(endpoint);
44
38
  }
45
39
 
46
40
  }
@@ -59,12 +53,7 @@ export class ElectronCustomEditorWidgetFactory extends CustomEditorWidgetFactory
59
53
  * @param endpoint cookie's target url
60
54
  */
61
55
  protected async attachElectronSecurityCookie(endpoint: string): Promise<void> {
62
- await electronRemote.session.defaultSession.cookies.set({
63
- url: endpoint,
64
- name: ElectronSecurityToken,
65
- value: JSON.stringify(this.container.get(ElectronSecurityToken)),
66
- httpOnly: true
67
- });
56
+ return window.electronTheiaCore.attachSecurityToken(endpoint);
68
57
  }
69
58
 
70
59
  }
@@ -14,11 +14,11 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import { injectable } from '@theia/core/shared/inversify';
18
- import * as fs from 'fs';
17
+ import { RequestContext, RequestService } from '@theia/core/shared/@theia/request';
18
+ import { inject, injectable } from '@theia/core/shared/inversify';
19
+ import { promises as fs, existsSync, mkdirSync } from 'fs';
19
20
  import * as os from 'os';
20
21
  import * as path from 'path';
21
- import * as request from 'request';
22
22
  import { PluginDeployerResolver, PluginDeployerResolverContext } from '../../common';
23
23
 
24
24
  /**
@@ -35,10 +35,13 @@ export class GithubPluginDeployerResolver implements PluginDeployerResolver {
35
35
 
36
36
  private unpackedFolder: string;
37
37
 
38
+ @inject(RequestService)
39
+ protected readonly request: RequestService;
40
+
38
41
  constructor() {
39
42
  this.unpackedFolder = path.resolve(os.tmpdir(), 'github-remote');
40
- if (!fs.existsSync(this.unpackedFolder)) {
41
- fs.mkdirSync(this.unpackedFolder);
43
+ if (!existsSync(this.unpackedFolder)) {
44
+ mkdirSync(this.unpackedFolder);
42
45
  }
43
46
  }
44
47
 
@@ -48,95 +51,76 @@ export class GithubPluginDeployerResolver implements PluginDeployerResolver {
48
51
  async resolve(pluginResolverContext: PluginDeployerResolverContext): Promise<void> {
49
52
 
50
53
  // download the file
51
- return new Promise<void>((resolve, reject) => {
52
- // extract data
53
- const extracted = /^github:(.*)\/(.*)\/(.*)$/gm.exec(pluginResolverContext.getOriginId());
54
- if (!extracted || extracted === null || extracted.length !== 4) {
55
- reject(new Error('Invalid extension' + pluginResolverContext.getOriginId()));
56
- return;
57
- }
54
+ // extract data
55
+ const extracted = /^github:(.*)\/(.*)\/(.*)$/gm.exec(pluginResolverContext.getOriginId());
56
+ if (!extracted || extracted === null || extracted.length !== 4) {
57
+ throw new Error('Invalid extension' + pluginResolverContext.getOriginId());
58
+ }
58
59
 
59
- const orgName = extracted[1];
60
- const repoName = extracted[2];
61
- const file = extracted[3];
62
-
63
- // get version if any
64
- const splitFile = file.split('@');
65
- let version;
66
- let filename: string;
67
- if (splitFile.length === 1) {
68
- filename = file;
69
- version = 'latest';
70
- } else {
71
- filename = splitFile[0];
72
- version = splitFile[1];
73
- }
74
- // latest version, need to get the redirect
75
- const url = GithubPluginDeployerResolver.GITHUB_ENDPOINT + orgName + '/' + repoName + '/releases/latest';
60
+ const orgName = extracted[1];
61
+ const repoName = extracted[2];
62
+ const file = extracted[3];
63
+
64
+ // get version if any
65
+ const splitFile = file.split('@');
66
+ let version;
67
+ let filename: string;
68
+ if (splitFile.length === 1) {
69
+ filename = file;
70
+ version = 'latest';
71
+ } else {
72
+ filename = splitFile[0];
73
+ version = splitFile[1];
74
+ }
75
+ // latest version, need to get the redirect
76
+ const url = GithubPluginDeployerResolver.GITHUB_ENDPOINT + orgName + '/' + repoName + '/releases/latest';
76
77
 
78
+ // if latest, resolve first the real version
79
+ if (version === 'latest') {
77
80
  // disable redirect to grab the release
78
- const options = {
79
- followRedirect: false
80
- };
81
- // if latest, resolve first the real version
82
- if (version === 'latest') {
83
- request.get(url, options).on('response', response => {
84
-
85
- // should have a redirect
86
- if (response.statusCode === 302) {
87
- const redirectLocation = response.headers.location;
88
- if (!redirectLocation) {
89
- reject(new Error('Invalid github link with latest not being found'));
90
- return;
91
- }
92
-
93
- // parse redirect link
94
- const taggedValueArray = /^https:\/\/.*tag\/(.*)/gm.exec(redirectLocation);
95
- if (!taggedValueArray || taggedValueArray.length !== 2) {
96
- reject(new Error('The redirect link for latest is invalid ' + redirectLocation));
97
- return;
98
- }
99
-
100
- // grab version of tag
101
- this.grabGithubFile(pluginResolverContext, orgName, repoName, filename, taggedValueArray[1], resolve, reject);
102
-
103
- }
104
- });
105
- } else {
106
- this.grabGithubFile(pluginResolverContext, orgName, repoName, filename, version, resolve, reject);
107
- }
108
-
109
- });
81
+ const followRedirects = 0;
82
+ const response = await this.request.request({ url, followRedirects });
83
+ // should have a redirect
84
+ if (response.res.statusCode === 302) {
85
+ const redirectLocation = response.res.headers.location;
86
+ if (!redirectLocation) {
87
+ throw new Error('Invalid github link with latest not being found');
88
+ }
89
+
90
+ // parse redirect link
91
+ const taggedValueArray = /^https:\/\/.*tag\/(.*)/gm.exec(redirectLocation);
92
+ if (!taggedValueArray || taggedValueArray.length !== 2) {
93
+ throw new Error('The redirect link for latest is invalid ' + redirectLocation);
94
+ }
95
+
96
+ // grab version of tag
97
+ return this.grabGithubFile(pluginResolverContext, orgName, repoName, filename, taggedValueArray[1]);
110
98
 
99
+ }
100
+ } else {
101
+ return this.grabGithubFile(pluginResolverContext, orgName, repoName, filename, version);
102
+ }
111
103
  }
112
104
 
113
105
  /*
114
106
  * Grab the github file specified by the plugin's ID
115
107
  */
116
- protected grabGithubFile(pluginResolverContext: PluginDeployerResolverContext, orgName: string, repoName: string, filename: string, version: string,
117
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
118
- resolve: (value?: void | PromiseLike<void>) => void, reject: (reason?: any) => void): void {
119
-
108
+ protected async grabGithubFile(pluginResolverContext: PluginDeployerResolverContext, orgName: string, repoName: string, filename: string, version: string): Promise<void> {
120
109
  const unpackedPath = path.resolve(this.unpackedFolder, path.basename(version + filename));
121
- const finish = () => {
122
- pluginResolverContext.addPlugin(pluginResolverContext.getOriginId(), unpackedPath);
123
- resolve();
124
- };
125
-
126
- // use of cache. If file is already there use it directly
127
- if (fs.existsSync(unpackedPath)) {
128
- finish();
110
+ try {
111
+ await fs.access(unpackedPath);
112
+ // use of cache. If file is already there use it directly
129
113
  return;
130
- }
131
- const dest = fs.createWriteStream(unpackedPath);
114
+ } catch { }
132
115
 
133
- dest.addListener('finish', finish);
134
116
  const url = GithubPluginDeployerResolver.GITHUB_ENDPOINT + orgName + '/' + repoName + '/releases/download/' + version + '/' + filename;
135
- request.get(url)
136
- .on('error', err => {
137
- reject(err);
138
- }).pipe(dest);
139
-
117
+ const response = await this.request.request({ url });
118
+ if (RequestContext.isSuccess(response)) {
119
+ await fs.writeFile(unpackedPath, response.buffer);
120
+ pluginResolverContext.addPlugin(pluginResolverContext.getOriginId(), unpackedPath);
121
+ } else {
122
+ throw new Error(`Could not download the plugin from GitHub. URL: ${url}. HTTP status code: ${response.res.statusCode}`);
123
+ }
140
124
  }
141
125
 
142
126
  /**
@@ -14,13 +14,12 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import { injectable } from '@theia/core/shared/inversify';
18
- import * as fs from 'fs';
17
+ import { RequestContext, RequestService } from '@theia/core/shared/@theia/request';
18
+ import { inject, injectable } from '@theia/core/shared/inversify';
19
+ import { promises as fs, existsSync, mkdirSync } from 'fs';
19
20
  import * as os from 'os';
20
21
  import * as path from 'path';
21
22
  import * as url from 'url';
22
- import * as request from 'request';
23
-
24
23
  import { PluginDeployerResolver, PluginDeployerResolverContext } from '../../common';
25
24
 
26
25
  /**
@@ -33,10 +32,13 @@ export class HttpPluginDeployerResolver implements PluginDeployerResolver {
33
32
 
34
33
  private unpackedFolder: string;
35
34
 
35
+ @inject(RequestService)
36
+ protected readonly request: RequestService;
37
+
36
38
  constructor() {
37
39
  this.unpackedFolder = path.resolve(os.tmpdir(), 'http-remote');
38
- if (!fs.existsSync(this.unpackedFolder)) {
39
- fs.mkdirSync(this.unpackedFolder);
40
+ if (!existsSync(this.unpackedFolder)) {
41
+ mkdirSync(this.unpackedFolder);
40
42
  }
41
43
  }
42
44
 
@@ -46,39 +48,31 @@ export class HttpPluginDeployerResolver implements PluginDeployerResolver {
46
48
  async resolve(pluginResolverContext: PluginDeployerResolverContext): Promise<void> {
47
49
 
48
50
  // download the file
49
- return new Promise<void>((resolve, reject) => {
50
-
51
- // keep filename of the url
52
- const urlPath = pluginResolverContext.getOriginId();
53
- const link = url.parse(urlPath);
54
- if (!link.pathname) {
55
- reject(new Error('invalid link URI' + urlPath));
56
- return;
57
- }
58
-
59
- const dirname = path.dirname(link.pathname);
60
- const basename = path.basename(link.pathname);
61
- const filename = dirname.replace(/\W/g, '_') + ('-') + basename;
62
- const unpackedPath = path.resolve(this.unpackedFolder, path.basename(filename));
51
+ // keep filename of the url
52
+ const urlPath = pluginResolverContext.getOriginId();
53
+ const link = url.parse(urlPath);
54
+ if (!link.pathname) {
55
+ throw new Error('invalid link URI' + urlPath);
56
+ }
63
57
 
64
- const finish = () => {
65
- pluginResolverContext.addPlugin(pluginResolverContext.getOriginId(), unpackedPath);
66
- resolve();
67
- };
58
+ const dirname = path.dirname(link.pathname);
59
+ const basename = path.basename(link.pathname);
60
+ const filename = dirname.replace(/\W/g, '_') + ('-') + basename;
61
+ const unpackedPath = path.resolve(this.unpackedFolder, path.basename(filename));
68
62
 
63
+ try {
64
+ await fs.access(unpackedPath);
69
65
  // use of cache. If file is already there use it directly
70
- if (fs.existsSync(unpackedPath)) {
71
- finish();
72
- return;
73
- }
74
- const dest = fs.createWriteStream(unpackedPath);
66
+ return;
67
+ } catch { }
75
68
 
76
- dest.addListener('finish', finish);
77
- request.get(pluginResolverContext.getOriginId())
78
- .on('error', err => {
79
- reject(err);
80
- }).pipe(dest);
81
- });
69
+ const response = await this.request.request({ url: pluginResolverContext.getOriginId() });
70
+ if (RequestContext.isSuccess(response)) {
71
+ await fs.writeFile(unpackedPath, response.buffer);
72
+ pluginResolverContext.addPlugin(pluginResolverContext.getOriginId(), unpackedPath);
73
+ } else {
74
+ throw new Error(`Could not download the plugin from ${pluginResolverContext.getOriginId()}. HTTP status code: ${response.res.statusCode}`);
75
+ }
82
76
 
83
77
  }
84
78
 
@@ -62,7 +62,7 @@ export class PluginsKeyValueStorage {
62
62
 
63
63
  const data = await this.readFromFile(dataPath);
64
64
 
65
- if (value === undefined || value === {}) {
65
+ if (value === undefined) {
66
66
  delete data[key];
67
67
  } else {
68
68
  data[key] = value;
@@ -18,10 +18,11 @@ import * as theia from '@theia/plugin';
18
18
  import { RPCProtocol } from '../common/rpc-protocol';
19
19
  import { CommandRegistryImpl } from './command-registry';
20
20
  import { UriComponents } from '../common/uri-components';
21
- import { CommentThreadCollapsibleState, URI } from './types-impl';
21
+ import { CommentThreadCollapsibleState, CommentThreadState, URI } from './types-impl';
22
22
  import {
23
23
  Range,
24
24
  Comment,
25
+ CommentThreadState as CommentThreadStateModel,
25
26
  CommentThreadCollapsibleState as CommentThreadCollapsibleStateModel,
26
27
  CommentOptions
27
28
  } from '../common/plugin-api-rpc-model';
@@ -185,6 +186,7 @@ type CommentThreadModification = Partial<{
185
186
  contextValue: string | undefined,
186
187
  comments: theia.Comment[],
187
188
  collapsibleState: theia.CommentThreadCollapsibleState
189
+ state: theia.CommentThreadState
188
190
  canReply: boolean;
189
191
  }>;
190
192
 
@@ -276,6 +278,20 @@ export class ExtHostCommentThread implements theia.CommentThread, theia.Disposab
276
278
  this._onDidUpdateCommentThread.fire();
277
279
  }
278
280
 
281
+ private _state?: theia.CommentThreadState;
282
+
283
+ get state(): theia.CommentThreadState {
284
+ return this._state!;
285
+ }
286
+
287
+ set state(newState: theia.CommentThreadState) {
288
+ if (this._state !== newState) {
289
+ this._state = newState;
290
+ this.modifications.state = newState;
291
+ this._onDidUpdateCommentThread.fire();
292
+ }
293
+ }
294
+
279
295
  private localDisposables: Disposable[];
280
296
 
281
297
  private _isDisposed: boolean;
@@ -357,6 +373,9 @@ export class ExtHostCommentThread implements theia.CommentThread, theia.Disposab
357
373
  if (modified('collapsibleState')) {
358
374
  formattedModifications.collapseState = convertToCollapsibleState(this.collapseState);
359
375
  }
376
+ if (modified('state')) {
377
+ formattedModifications.state = convertToState(this._state);
378
+ }
360
379
  if (modified('canReply')) {
361
380
  formattedModifications.canReply = this.canReply;
362
381
  }
@@ -516,3 +535,15 @@ function convertToCollapsibleState(kind: theia.CommentThreadCollapsibleState | u
516
535
  }
517
536
  return CommentThreadCollapsibleStateModel.Collapsed;
518
537
  }
538
+
539
+ function convertToState(kind: theia.CommentThreadState | undefined): CommentThreadStateModel {
540
+ if (kind !== undefined) {
541
+ switch (kind) {
542
+ case CommentThreadState.Resolved:
543
+ return CommentThreadStateModel.Resolved;
544
+ case CommentThreadState.Unresolved:
545
+ return CommentThreadStateModel.Unresolved;
546
+ }
547
+ }
548
+ return CommentThreadStateModel.Unresolved;
549
+ }
@@ -0,0 +1,84 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2023 TypeFox 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
+ /* eslint-disable @typescript-eslint/no-explicit-any */
18
+
19
+ import { nls } from '@theia/core';
20
+ import { Localization } from '@theia/core/lib/common/i18n/localization';
21
+ import { LocalizationExt, LocalizationMain, Plugin, PLUGIN_RPC_CONTEXT, StringDetails } from '../common';
22
+ import { LanguagePackBundle } from '../common/language-pack-service';
23
+ import { RPCProtocol } from '../common/rpc-protocol';
24
+ import { URI } from './types-impl';
25
+
26
+ export class LocalizationExtImpl implements LocalizationExt {
27
+
28
+ private readonly _proxy: LocalizationMain;
29
+ private currentLanguage?: string;
30
+ private isDefaultLanguage = true;
31
+ private readonly bundleCache = new Map<string, LanguagePackBundle | undefined>();
32
+
33
+ constructor(rpc: RPCProtocol) {
34
+ this._proxy = rpc.getProxy(PLUGIN_RPC_CONTEXT.LOCALIZATION_MAIN);
35
+ }
36
+
37
+ translateMessage(pluginId: string, details: StringDetails): string {
38
+ const { message, args, comment } = details;
39
+ if (this.isDefaultLanguage) {
40
+ return Localization.format(message, (args ?? {}));
41
+ }
42
+
43
+ let key = message;
44
+ if (comment && comment.length > 0) {
45
+ key += `/${Array.isArray(comment) ? comment.join() : comment}`;
46
+ }
47
+ const str = this.bundleCache.get(pluginId)?.contents[key];
48
+ return Localization.format(str ?? message, (args ?? {}));
49
+ }
50
+
51
+ getBundle(pluginId: string): { [key: string]: string } | undefined {
52
+ return this.bundleCache.get(pluginId)?.contents;
53
+ }
54
+
55
+ getBundleUri(pluginId: string): URI | undefined {
56
+ const uri = this.bundleCache.get(pluginId)?.uri;
57
+ return uri ? URI.parse(uri) : undefined;
58
+ }
59
+
60
+ async initializeLocalizedMessages(plugin: Plugin, currentLanguage: string): Promise<void> {
61
+ this.currentLanguage ??= currentLanguage;
62
+ this.isDefaultLanguage = this.currentLanguage === nls.defaultLocale;
63
+
64
+ if (this.isDefaultLanguage) {
65
+ return;
66
+ }
67
+
68
+ if (this.bundleCache.has(plugin.model.id)) {
69
+ return;
70
+ }
71
+
72
+ let bundle: LanguagePackBundle | undefined;
73
+
74
+ try {
75
+ bundle = await this._proxy.$fetchBundle(plugin.model.id);
76
+ } catch (e) {
77
+ console.error(`Failed to load translations for ${plugin.model.id}: ${e.message}`);
78
+ return;
79
+ }
80
+
81
+ this.bundleCache.set(plugin.model.id, bundle);
82
+ }
83
+
84
+ }