@theia/core 1.44.0 → 1.45.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 (260) hide show
  1. package/README.md +6 -6
  2. package/i18n/nls.cs.json +10 -3
  3. package/i18n/nls.de.json +10 -3
  4. package/i18n/nls.es.json +10 -3
  5. package/i18n/nls.fr.json +10 -3
  6. package/i18n/nls.hu.json +10 -3
  7. package/i18n/nls.it.json +10 -3
  8. package/i18n/nls.ja.json +10 -3
  9. package/i18n/nls.json +10 -3
  10. package/i18n/nls.pl.json +10 -3
  11. package/i18n/nls.pt-br.json +10 -3
  12. package/i18n/nls.pt-pt.json +10 -3
  13. package/i18n/nls.ru.json +10 -3
  14. package/i18n/nls.zh-cn.json +10 -3
  15. package/lib/browser/common-frontend-contribution.d.ts +6 -0
  16. package/lib/browser/common-frontend-contribution.d.ts.map +1 -1
  17. package/lib/browser/common-frontend-contribution.js +52 -9
  18. package/lib/browser/common-frontend-contribution.js.map +1 -1
  19. package/lib/browser/connection-status-service.d.ts +2 -2
  20. package/lib/browser/connection-status-service.d.ts.map +1 -1
  21. package/lib/browser/connection-status-service.js +3 -3
  22. package/lib/browser/connection-status-service.js.map +1 -1
  23. package/lib/browser/connection-status-service.spec.js +6 -6
  24. package/lib/browser/connection-status-service.spec.js.map +1 -1
  25. package/lib/browser/core-preferences.d.ts.map +1 -1
  26. package/lib/browser/core-preferences.js +16 -0
  27. package/lib/browser/core-preferences.js.map +1 -1
  28. package/lib/browser/dialogs.d.ts +0 -1
  29. package/lib/browser/dialogs.d.ts.map +1 -1
  30. package/lib/browser/dialogs.js +1 -34
  31. package/lib/browser/dialogs.js.map +1 -1
  32. package/lib/browser/frontend-application-module.d.ts.map +1 -1
  33. package/lib/browser/frontend-application-module.js +1 -0
  34. package/lib/browser/frontend-application-module.js.map +1 -1
  35. package/lib/browser/messaging/connection-source.d.ts +9 -0
  36. package/lib/browser/messaging/connection-source.d.ts.map +1 -0
  37. package/lib/browser/messaging/connection-source.js +20 -0
  38. package/lib/browser/messaging/connection-source.js.map +1 -0
  39. package/lib/browser/messaging/frontend-id-provider.d.ts +13 -0
  40. package/lib/browser/messaging/frontend-id-provider.d.ts.map +1 -0
  41. package/lib/browser/messaging/frontend-id-provider.js +40 -0
  42. package/lib/browser/messaging/frontend-id-provider.js.map +1 -0
  43. package/lib/browser/messaging/messaging-frontend-module.d.ts.map +1 -1
  44. package/lib/browser/messaging/messaging-frontend-module.js +18 -1
  45. package/lib/browser/messaging/messaging-frontend-module.js.map +1 -1
  46. package/lib/browser/messaging/service-connection-provider.d.ts +48 -0
  47. package/lib/browser/messaging/service-connection-provider.d.ts.map +1 -0
  48. package/lib/browser/messaging/service-connection-provider.js +115 -0
  49. package/lib/browser/messaging/service-connection-provider.js.map +1 -0
  50. package/lib/browser/messaging/ws-connection-provider.d.ts +7 -38
  51. package/lib/browser/messaging/ws-connection-provider.d.ts.map +1 -1
  52. package/lib/browser/messaging/ws-connection-provider.js +17 -121
  53. package/lib/browser/messaging/ws-connection-provider.js.map +1 -1
  54. package/lib/browser/messaging/ws-connection-source.d.ts +41 -0
  55. package/lib/browser/messaging/ws-connection-source.d.ts.map +1 -0
  56. package/lib/browser/messaging/ws-connection-source.js +210 -0
  57. package/lib/browser/messaging/ws-connection-source.js.map +1 -0
  58. package/lib/browser/preload/i18n-preload-contribution.js +1 -1
  59. package/lib/browser/preload/i18n-preload-contribution.js.map +1 -1
  60. package/lib/browser/shell/application-shell.js +1 -1
  61. package/lib/browser/shell/application-shell.js.map +1 -1
  62. package/lib/browser/tree/tree-compression/compressed-tree-widget.d.ts +1 -0
  63. package/lib/browser/tree/tree-compression/compressed-tree-widget.d.ts.map +1 -1
  64. package/lib/browser/tree/tree-compression/compressed-tree-widget.js +5 -0
  65. package/lib/browser/tree/tree-compression/compressed-tree-widget.js.map +1 -1
  66. package/lib/browser/tree/tree-widget.d.ts +6 -0
  67. package/lib/browser/tree/tree-widget.d.ts.map +1 -1
  68. package/lib/browser/tree/tree-widget.js +21 -11
  69. package/lib/browser/tree/tree-widget.js.map +1 -1
  70. package/lib/browser/user-working-directory-provider.d.ts +8 -1
  71. package/lib/browser/user-working-directory-provider.d.ts.map +1 -1
  72. package/lib/browser/user-working-directory-provider.js +22 -1
  73. package/lib/browser/user-working-directory-provider.js.map +1 -1
  74. package/lib/browser/window/default-secondary-window-service.d.ts +3 -0
  75. package/lib/browser/window/default-secondary-window-service.d.ts.map +1 -1
  76. package/lib/browser/window/default-secondary-window-service.js +55 -1
  77. package/lib/browser/window/default-secondary-window-service.js.map +1 -1
  78. package/lib/common/message-rpc/channel.d.ts.map +1 -1
  79. package/lib/common/message-rpc/channel.js +7 -1
  80. package/lib/common/message-rpc/channel.js.map +1 -1
  81. package/lib/common/message-rpc/message-buffer.d.ts +2 -0
  82. package/lib/common/message-rpc/message-buffer.d.ts.map +1 -1
  83. package/lib/common/message-rpc/message-buffer.js +4 -0
  84. package/lib/common/message-rpc/message-buffer.js.map +1 -1
  85. package/lib/common/message-rpc/uint8-array-message-buffer.d.ts +1 -0
  86. package/lib/common/message-rpc/uint8-array-message-buffer.d.ts.map +1 -1
  87. package/lib/common/message-rpc/uint8-array-message-buffer.js +6 -0
  88. package/lib/common/message-rpc/uint8-array-message-buffer.js.map +1 -1
  89. package/lib/common/messaging/connection-management.d.ts +25 -0
  90. package/lib/common/messaging/connection-management.d.ts.map +1 -0
  91. package/lib/common/messaging/connection-management.js +38 -0
  92. package/lib/common/messaging/connection-management.js.map +1 -0
  93. package/lib/common/messaging/handler.d.ts +1 -0
  94. package/lib/common/messaging/handler.d.ts.map +1 -1
  95. package/lib/common/messaging/handler.js +2 -1
  96. package/lib/common/messaging/handler.js.map +1 -1
  97. package/lib/common/messaging/socket-write-buffer.d.ts +11 -0
  98. package/lib/common/messaging/socket-write-buffer.d.ts.map +1 -0
  99. package/lib/common/messaging/socket-write-buffer.js +50 -0
  100. package/lib/common/messaging/socket-write-buffer.js.map +1 -0
  101. package/lib/common/messaging/web-socket-channel.d.ts +7 -35
  102. package/lib/common/messaging/web-socket-channel.d.ts.map +1 -1
  103. package/lib/common/messaging/web-socket-channel.js +20 -9
  104. package/lib/common/messaging/web-socket-channel.js.map +1 -1
  105. package/lib/electron-browser/messaging/electron-frontend-id-provider.d.ts +5 -0
  106. package/lib/electron-browser/messaging/electron-frontend-id-provider.d.ts.map +1 -0
  107. package/lib/{electron-node/token/electron-token-messaging-contribution.js → electron-browser/messaging/electron-frontend-id-provider.js} +9 -28
  108. package/lib/electron-browser/messaging/electron-frontend-id-provider.js.map +1 -0
  109. package/lib/electron-browser/messaging/electron-ipc-connection-source.d.ts +24 -0
  110. package/lib/electron-browser/messaging/electron-ipc-connection-source.d.ts.map +1 -0
  111. package/lib/electron-browser/messaging/{electron-ipc-connection-provider.js → electron-ipc-connection-source.js} +19 -19
  112. package/lib/electron-browser/messaging/electron-ipc-connection-source.js.map +1 -0
  113. package/lib/electron-browser/messaging/electron-local-ws-connection-source.d.ts +7 -0
  114. package/lib/electron-browser/messaging/electron-local-ws-connection-source.d.ts.map +1 -0
  115. package/lib/electron-browser/messaging/{electron-local-ws-connection-provider.js → electron-local-ws-connection-source.js} +7 -7
  116. package/lib/electron-browser/messaging/electron-local-ws-connection-source.js.map +1 -0
  117. package/lib/electron-browser/messaging/electron-messaging-frontend-module.d.ts.map +1 -1
  118. package/lib/electron-browser/messaging/electron-messaging-frontend-module.js +45 -13
  119. package/lib/electron-browser/messaging/electron-messaging-frontend-module.js.map +1 -1
  120. package/lib/electron-browser/messaging/electron-ws-connection-source.d.ts +12 -0
  121. package/lib/electron-browser/messaging/electron-ws-connection-source.d.ts.map +1 -0
  122. package/lib/electron-browser/messaging/{electron-ws-connection-provider.js → electron-ws-connection-source.js} +14 -21
  123. package/lib/electron-browser/messaging/electron-ws-connection-source.js.map +1 -0
  124. package/lib/electron-browser/preload.d.ts.map +1 -1
  125. package/lib/electron-browser/preload.js +10 -0
  126. package/lib/electron-browser/preload.js.map +1 -1
  127. package/lib/electron-browser/window/electron-window-module.js +2 -2
  128. package/lib/electron-browser/window/electron-window-module.js.map +1 -1
  129. package/lib/electron-browser/window/electron-window-service.d.ts +4 -0
  130. package/lib/electron-browser/window/electron-window-service.d.ts.map +1 -1
  131. package/lib/electron-browser/window/electron-window-service.js +13 -0
  132. package/lib/electron-browser/window/electron-window-service.js.map +1 -1
  133. package/lib/electron-common/electron-api.d.ts +6 -0
  134. package/lib/electron-common/electron-api.d.ts.map +1 -1
  135. package/lib/electron-common/electron-api.js +3 -1
  136. package/lib/electron-common/electron-api.js.map +1 -1
  137. package/lib/electron-main/electron-api-main.d.ts +1 -0
  138. package/lib/electron-main/electron-api-main.d.ts.map +1 -1
  139. package/lib/electron-main/electron-api-main.js +15 -0
  140. package/lib/electron-main/electron-api-main.js.map +1 -1
  141. package/lib/electron-main/electron-main-application-module.js +5 -5
  142. package/lib/electron-main/electron-main-application-module.js.map +1 -1
  143. package/lib/electron-main/electron-main-application.d.ts +7 -13
  144. package/lib/electron-main/electron-main-application.d.ts.map +1 -1
  145. package/lib/electron-main/electron-main-application.js +36 -26
  146. package/lib/electron-main/electron-main-application.js.map +1 -1
  147. package/lib/electron-main/messaging/electron-connection-handler.d.ts.map +1 -0
  148. package/lib/electron-main/messaging/electron-connection-handler.js.map +1 -0
  149. package/lib/electron-main/messaging/electron-messaging-contribution.d.ts +13 -22
  150. package/lib/electron-main/messaging/electron-messaging-contribution.d.ts.map +1 -1
  151. package/lib/electron-main/messaging/electron-messaging-contribution.js +39 -39
  152. package/lib/electron-main/messaging/electron-messaging-contribution.js.map +1 -1
  153. package/lib/electron-main/messaging/electron-messaging-service.d.ts.map +1 -1
  154. package/lib/electron-main/messaging/electron-messaging-service.js.map +1 -1
  155. package/lib/electron-main/theia-electron-window.d.ts +2 -2
  156. package/lib/electron-main/theia-electron-window.d.ts.map +1 -1
  157. package/lib/electron-main/theia-electron-window.js +3 -2
  158. package/lib/electron-main/theia-electron-window.js.map +1 -1
  159. package/lib/node/messaging/default-messaging-service.d.ts +29 -0
  160. package/lib/node/messaging/default-messaging-service.d.ts.map +1 -0
  161. package/lib/node/messaging/default-messaging-service.js +140 -0
  162. package/lib/node/messaging/default-messaging-service.js.map +1 -0
  163. package/lib/node/messaging/frontend-connection-service.d.ts +7 -0
  164. package/lib/node/messaging/frontend-connection-service.d.ts.map +1 -0
  165. package/lib/node/messaging/frontend-connection-service.js +19 -0
  166. package/lib/node/messaging/frontend-connection-service.js.map +1 -0
  167. package/lib/node/messaging/messaging-backend-module.d.ts.map +1 -1
  168. package/lib/node/messaging/messaging-backend-module.js +23 -9
  169. package/lib/node/messaging/messaging-backend-module.js.map +1 -1
  170. package/lib/node/messaging/messaging-service.d.ts +2 -3
  171. package/lib/node/messaging/messaging-service.d.ts.map +1 -1
  172. package/lib/node/messaging/test/test-web-socket-channel.d.ts +3 -3
  173. package/lib/node/messaging/test/test-web-socket-channel.d.ts.map +1 -1
  174. package/lib/node/messaging/test/test-web-socket-channel.js +38 -24
  175. package/lib/node/messaging/test/test-web-socket-channel.js.map +1 -1
  176. package/lib/node/messaging/websocket-endpoint.d.ts +21 -0
  177. package/lib/node/messaging/websocket-endpoint.d.ts.map +1 -0
  178. package/lib/node/messaging/websocket-endpoint.js +89 -0
  179. package/lib/node/messaging/websocket-endpoint.js.map +1 -0
  180. package/lib/node/messaging/websocket-frontend-connection-service.d.ts +30 -0
  181. package/lib/node/messaging/websocket-frontend-connection-service.d.ts.map +1 -0
  182. package/lib/node/messaging/websocket-frontend-connection-service.js +173 -0
  183. package/lib/node/messaging/websocket-frontend-connection-service.js.map +1 -0
  184. package/package.json +6 -6
  185. package/src/browser/common-frontend-contribution.ts +55 -9
  186. package/src/browser/connection-status-service.spec.ts +6 -6
  187. package/src/browser/connection-status-service.ts +2 -2
  188. package/src/browser/core-preferences.ts +16 -0
  189. package/src/browser/dialogs.ts +0 -34
  190. package/src/browser/frontend-application-module.ts +1 -0
  191. package/src/browser/messaging/connection-source.ts +26 -0
  192. package/src/browser/messaging/frontend-id-provider.ts +37 -0
  193. package/src/browser/messaging/messaging-frontend-module.ts +20 -2
  194. package/src/browser/messaging/service-connection-provider.ts +126 -0
  195. package/src/browser/messaging/ws-connection-provider.ts +16 -141
  196. package/src/browser/messaging/ws-connection-source.ts +210 -0
  197. package/src/browser/preload/i18n-preload-contribution.ts +1 -1
  198. package/src/browser/shell/application-shell.ts +1 -1
  199. package/src/browser/tree/tree-compression/compressed-tree-widget.tsx +27 -7
  200. package/src/browser/tree/tree-widget.tsx +21 -10
  201. package/src/browser/user-working-directory-provider.ts +32 -3
  202. package/src/browser/window/default-secondary-window-service.ts +54 -1
  203. package/src/common/i18n/nls.metadata.json +7208 -6923
  204. package/src/common/message-rpc/channel.ts +5 -1
  205. package/src/common/message-rpc/message-buffer.ts +6 -0
  206. package/src/common/message-rpc/uint8-array-message-buffer.ts +7 -0
  207. package/src/common/messaging/connection-management.ts +43 -0
  208. package/src/common/messaging/handler.ts +2 -0
  209. package/src/common/messaging/socket-write-buffer.ts +52 -0
  210. package/src/common/messaging/web-socket-channel.ts +28 -45
  211. package/src/electron-browser/messaging/electron-frontend-id-provider.ts +25 -0
  212. package/src/electron-browser/messaging/{electron-ipc-connection-provider.ts → electron-ipc-connection-source.ts} +17 -13
  213. package/src/electron-browser/messaging/{electron-local-ws-connection-provider.ts → electron-local-ws-connection-source.ts} +2 -2
  214. package/src/electron-browser/messaging/electron-messaging-frontend-module.ts +49 -12
  215. package/src/electron-browser/messaging/{electron-ws-connection-provider.ts → electron-ws-connection-source.ts} +6 -17
  216. package/src/electron-browser/preload.ts +15 -1
  217. package/src/electron-browser/window/electron-window-module.ts +1 -1
  218. package/src/electron-browser/window/electron-window-service.ts +11 -0
  219. package/src/electron-common/electron-api.ts +7 -0
  220. package/src/electron-main/electron-api-main.ts +20 -1
  221. package/src/electron-main/electron-main-application-module.ts +5 -5
  222. package/src/electron-main/electron-main-application.ts +46 -41
  223. package/src/electron-main/messaging/electron-messaging-contribution.ts +45 -43
  224. package/src/electron-main/messaging/electron-messaging-service.ts +1 -0
  225. package/src/electron-main/theia-electron-window.ts +4 -3
  226. package/src/node/messaging/default-messaging-service.ts +129 -0
  227. package/src/node/messaging/frontend-connection-service.ts +24 -0
  228. package/src/node/messaging/messaging-backend-module.ts +25 -10
  229. package/src/node/messaging/messaging-service.ts +3 -3
  230. package/src/node/messaging/test/test-web-socket-channel.ts +32 -27
  231. package/src/node/messaging/websocket-endpoint.ts +79 -0
  232. package/src/node/messaging/websocket-frontend-connection-service.ts +171 -0
  233. package/lib/common/messaging/abstract-connection-provider.d.ts +0 -45
  234. package/lib/common/messaging/abstract-connection-provider.d.ts.map +0 -1
  235. package/lib/common/messaging/abstract-connection-provider.js +0 -93
  236. package/lib/common/messaging/abstract-connection-provider.js.map +0 -1
  237. package/lib/electron-browser/messaging/electron-ipc-connection-provider.d.ts +0 -19
  238. package/lib/electron-browser/messaging/electron-ipc-connection-provider.d.ts.map +0 -1
  239. package/lib/electron-browser/messaging/electron-ipc-connection-provider.js.map +0 -1
  240. package/lib/electron-browser/messaging/electron-local-ws-connection-provider.d.ts +0 -7
  241. package/lib/electron-browser/messaging/electron-local-ws-connection-provider.d.ts.map +0 -1
  242. package/lib/electron-browser/messaging/electron-local-ws-connection-provider.js.map +0 -1
  243. package/lib/electron-browser/messaging/electron-ws-connection-provider.d.ts +0 -17
  244. package/lib/electron-browser/messaging/electron-ws-connection-provider.d.ts.map +0 -1
  245. package/lib/electron-browser/messaging/electron-ws-connection-provider.js.map +0 -1
  246. package/lib/electron-common/messaging/electron-connection-handler.d.ts.map +0 -1
  247. package/lib/electron-common/messaging/electron-connection-handler.js.map +0 -1
  248. package/lib/electron-node/token/electron-token-messaging-contribution.d.ts +0 -16
  249. package/lib/electron-node/token/electron-token-messaging-contribution.d.ts.map +0 -1
  250. package/lib/electron-node/token/electron-token-messaging-contribution.js.map +0 -1
  251. package/lib/node/messaging/messaging-contribution.d.ts +0 -44
  252. package/lib/node/messaging/messaging-contribution.d.ts.map +0 -1
  253. package/lib/node/messaging/messaging-contribution.js +0 -210
  254. package/lib/node/messaging/messaging-contribution.js.map +0 -1
  255. package/src/common/messaging/abstract-connection-provider.ts +0 -115
  256. package/src/electron-node/token/electron-token-messaging-contribution.ts +0 -41
  257. package/src/node/messaging/messaging-contribution.ts +0 -197
  258. /package/lib/{electron-common → electron-main}/messaging/electron-connection-handler.d.ts +0 -0
  259. /package/lib/{electron-common → electron-main}/messaging/electron-connection-handler.js +0 -0
  260. /package/src/{electron-common → electron-main}/messaging/electron-connection-handler.ts +0 -0
@@ -0,0 +1,126 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2020 Ericsson 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-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { inject, injectable, interfaces, postConstruct } from 'inversify';
18
+ import { Channel, RpcProxy, RpcProxyFactory } from '../../common';
19
+ import { ChannelMultiplexer } from '../../common/message-rpc/channel';
20
+ import { Deferred } from '../../common/promise-util';
21
+ import { ConnectionSource } from './connection-source';
22
+
23
+ export const LocalConnectionProvider = Symbol('LocalConnectionProvider');
24
+ export const RemoteConnectionProvider = Symbol('RemoteConnectionProvider');
25
+
26
+ export namespace ServiceConnectionProvider {
27
+ export type ConnectionHandler = (path: String, channel: Channel) => void;
28
+ }
29
+
30
+ /**
31
+ * This class manages the channels for remote services in the back end
32
+ */
33
+ @injectable()
34
+ export class ServiceConnectionProvider {
35
+
36
+ static createProxy<T extends object>(container: interfaces.Container, path: string, arg?: object): RpcProxy<T> {
37
+ return container.get<ServiceConnectionProvider>(RemoteConnectionProvider).createProxy(path, arg);
38
+ }
39
+
40
+ static createLocalProxy<T extends object>(container: interfaces.Container, path: string, arg?: object): RpcProxy<T> {
41
+ return container.get<ServiceConnectionProvider>(LocalConnectionProvider).createProxy(path, arg);
42
+ }
43
+
44
+ static createHandler(container: interfaces.Container, path: string, arg?: object): void {
45
+ const remote = container.get<ServiceConnectionProvider>(RemoteConnectionProvider);
46
+ const local = container.get<ServiceConnectionProvider>(LocalConnectionProvider);
47
+ remote.createProxy(path, arg);
48
+ if (remote !== local) {
49
+ local.createProxy(path, arg);
50
+ }
51
+ }
52
+
53
+ protected readonly channelHandlers = new Map<string, ServiceConnectionProvider.ConnectionHandler>();
54
+
55
+ /**
56
+ * Create a proxy object to remote interface of T type
57
+ * over a web socket connection for the given path and proxy factory.
58
+ */
59
+ createProxy<T extends object>(path: string, factory: RpcProxyFactory<T>): RpcProxy<T>;
60
+ /**
61
+ * Create a proxy object to remote interface of T type
62
+ * over a web socket connection for the given path.
63
+ *
64
+ * An optional target can be provided to handle
65
+ * notifications and requests from a remote side.
66
+ */
67
+ createProxy<T extends object>(path: string, target?: object): RpcProxy<T>;
68
+ createProxy<T extends object>(path: string, arg?: object): RpcProxy<T> {
69
+ const factory = arg instanceof RpcProxyFactory ? arg : new RpcProxyFactory<T>(arg);
70
+ this.listen(path, (_, c) => factory.listen(c), true);
71
+ return factory.createProxy();
72
+ }
73
+
74
+ protected channelMultiplexer: ChannelMultiplexer;
75
+
76
+ private channelReadyDeferred = new Deferred<void>();
77
+ protected get channelReady(): Promise<void> {
78
+ return this.channelReadyDeferred.promise;
79
+ }
80
+
81
+ @postConstruct()
82
+ init(): void {
83
+ this.connectionSource.onConnectionDidOpen(channel => this.handleChannelCreated(channel));
84
+ }
85
+
86
+ @inject(ConnectionSource)
87
+ protected connectionSource: ConnectionSource;
88
+
89
+ /**
90
+ * This method must be invoked by subclasses when they have created the main channel.
91
+ * @param mainChannel
92
+ */
93
+ protected handleChannelCreated(channel: Channel): void {
94
+ channel.onClose(() => {
95
+ this.handleChannelClosed(channel);
96
+ });
97
+
98
+ this.channelMultiplexer = new ChannelMultiplexer(channel);
99
+ this.channelReadyDeferred.resolve();
100
+ for (const entry of this.channelHandlers.entries()) {
101
+ this.openChannel(entry[0], entry[1]);
102
+ }
103
+ }
104
+
105
+ handleChannelClosed(channel: Channel): void {
106
+ this.channelReadyDeferred = new Deferred();
107
+ }
108
+
109
+ /**
110
+ * Install a connection handler for the given path.
111
+ */
112
+ listen(path: string, handler: ServiceConnectionProvider.ConnectionHandler, reconnect: boolean): void {
113
+ this.openChannel(path, handler).then(() => {
114
+ if (reconnect) {
115
+ this.channelHandlers.set(path, handler);
116
+ }
117
+ });
118
+
119
+ }
120
+
121
+ private async openChannel(path: string, handler: ServiceConnectionProvider.ConnectionHandler): Promise<void> {
122
+ await this.channelReady;
123
+ const newChannel = await this.channelMultiplexer.open(path);
124
+ handler(path, newChannel);
125
+ }
126
+ }
@@ -14,160 +14,35 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import { injectable, interfaces, decorate, unmanaged } from 'inversify';
18
- import { RpcProxyFactory, RpcProxy, Emitter, Event, Channel } from '../../common';
19
- import { Endpoint } from '../endpoint';
20
- import { AbstractConnectionProvider } from '../../common/messaging/abstract-connection-provider';
21
- import { io, Socket } from 'socket.io-client';
22
- import { IWebSocket, WebSocketChannel } from '../../common/messaging/web-socket-channel';
17
+ import { injectable, interfaces, decorate, unmanaged, inject } from 'inversify';
18
+ import { RpcProxyFactory, RpcProxy } from '../../common';
19
+ import { RemoteConnectionProvider, ServiceConnectionProvider } from './service-connection-provider';
23
20
 
24
21
  decorate(injectable(), RpcProxyFactory);
25
22
  decorate(unmanaged(), RpcProxyFactory, 0);
26
23
 
27
- export const LocalWebSocketConnectionProvider = Symbol('LocalWebSocketConnectionProvider');
28
-
29
- export interface WebSocketOptions {
30
- /**
31
- * True by default.
32
- */
33
- reconnecting?: boolean;
34
- }
35
-
24
+ /**
25
+ * @deprecated This class serves to keep API compatibility for a while. Use {@linkcode ServiceConnectionProvider} instead.
26
+ */
36
27
  @injectable()
37
- export class WebSocketConnectionProvider extends AbstractConnectionProvider<WebSocketOptions> {
38
-
39
- protected readonly onSocketDidOpenEmitter: Emitter<void> = new Emitter();
40
- get onSocketDidOpen(): Event<void> {
41
- return this.onSocketDidOpenEmitter.event;
42
- }
43
-
44
- protected readonly onSocketDidCloseEmitter: Emitter<void> = new Emitter();
45
- get onSocketDidClose(): Event<void> {
46
- return this.onSocketDidCloseEmitter.event;
47
- }
28
+ export class WebSocketConnectionProvider {
29
+ @inject(RemoteConnectionProvider)
30
+ private readonly remoteConnectionProvider: ServiceConnectionProvider;
48
31
 
49
- static override createProxy<T extends object>(container: interfaces.Container, path: string, arg?: object): RpcProxy<T> {
50
- return container.get(WebSocketConnectionProvider).createProxy<T>(path, arg);
32
+ static createProxy<T extends object>(container: interfaces.Container, path: string, arg?: object): RpcProxy<T> {
33
+ return ServiceConnectionProvider.createProxy(container, path, arg);
51
34
  }
52
35
 
53
36
  static createLocalProxy<T extends object>(container: interfaces.Container, path: string, arg?: object): RpcProxy<T> {
54
- return container.get<WebSocketConnectionProvider>(LocalWebSocketConnectionProvider).createProxy<T>(path, arg);
37
+ return ServiceConnectionProvider.createLocalProxy(container, path, arg);
55
38
  }
56
39
 
57
40
  static createHandler(container: interfaces.Container, path: string, arg?: object): void {
58
- const remote = container.get(WebSocketConnectionProvider);
59
- const local = container.get<WebSocketConnectionProvider>(LocalWebSocketConnectionProvider);
60
- remote.createProxy(path, arg);
61
- if (remote !== local) {
62
- local.createProxy(path, arg);
63
- }
41
+ return ServiceConnectionProvider.createHandler(container, path, arg);
64
42
  }
65
43
 
66
- protected readonly socket: Socket;
67
-
68
- constructor() {
69
- super();
70
- const url = this.createWebSocketUrl(WebSocketChannel.wsPath);
71
- this.socket = this.createWebSocket(url);
72
- this.socket.on('connect', () => {
73
- this.initializeMultiplexer();
74
- if (this.reconnectChannelOpeners.length > 0) {
75
- this.reconnectChannelOpeners.forEach(opener => opener());
76
- this.reconnectChannelOpeners = [];
77
- }
78
- this.socket.on('disconnect', () => this.fireSocketDidClose());
79
- this.socket.on('message', () => this.onIncomingMessageActivityEmitter.fire(undefined));
80
- this.fireSocketDidOpen();
81
- });
82
- this.socket.connect();
83
- }
84
-
85
- protected createMainChannel(): Channel {
86
- return new WebSocketChannel(this.toIWebSocket(this.socket));
87
- }
88
-
89
- protected toIWebSocket(socket: Socket): IWebSocket {
90
- return {
91
- close: () => {
92
- socket.removeAllListeners('disconnect');
93
- socket.removeAllListeners('error');
94
- socket.removeAllListeners('message');
95
- },
96
- isConnected: () => socket.connected,
97
- onClose: cb => socket.on('disconnect', reason => cb(reason)),
98
- onError: cb => socket.on('error', reason => cb(reason)),
99
- onMessage: cb => socket.on('message', data => cb(data)),
100
- send: message => socket.emit('message', message)
101
- };
102
- }
103
-
104
- override async openChannel(path: string, handler: (channel: Channel) => void, options?: WebSocketOptions): Promise<void> {
105
- if (this.socket.connected) {
106
- return super.openChannel(path, handler, options);
107
- } else {
108
- const openChannel = () => {
109
- this.socket.off('connect', openChannel);
110
- this.openChannel(path, handler, options);
111
- };
112
- this.socket.on('connect', openChannel);
113
- }
114
- }
115
-
116
- /**
117
- * @param path The handler to reach in the backend.
118
- */
119
- protected createWebSocketUrl(path: string): string {
120
- // Since we are using Socket.io, the path should look like the following:
121
- // proto://domain.com/{path}
122
- return this.createEndpoint(path).getWebSocketUrl().withPath(path).toString();
123
- }
124
-
125
- protected createHttpWebSocketUrl(path: string): string {
126
- return this.createEndpoint(path).getRestUrl().toString();
127
- }
128
-
129
- protected createEndpoint(path: string): Endpoint {
130
- return new Endpoint({ path });
131
- }
132
-
133
- /**
134
- * Creates a web socket for the given url
135
- */
136
- protected createWebSocket(url: string): Socket {
137
- return io(url, {
138
- path: this.createSocketIoPath(url),
139
- reconnection: true,
140
- reconnectionDelay: 1000,
141
- reconnectionDelayMax: 10000,
142
- reconnectionAttempts: Infinity,
143
- extraHeaders: {
144
- // Socket.io strips the `origin` header
145
- // We need to provide our own for validation
146
- 'fix-origin': window.location.origin
147
- }
148
- });
149
- }
150
-
151
- /**
152
- * Path for Socket.io to make its requests to.
153
- */
154
- protected createSocketIoPath(url: string): string | undefined {
155
- if (location.protocol === Endpoint.PROTO_FILE) {
156
- return '/socket.io';
157
- }
158
- let { pathname } = location;
159
- if (!pathname.endsWith('/')) {
160
- pathname += '/';
161
- }
162
- return pathname + 'socket.io';
163
- }
164
-
165
- protected fireSocketDidOpen(): void {
166
- this.onSocketDidOpenEmitter.fire(undefined);
167
- }
168
-
169
- protected fireSocketDidClose(): void {
170
- this.onSocketDidCloseEmitter.fire(undefined);
44
+ createProxy<T extends object>(path: string, target?: object): RpcProxy<T>;
45
+ createProxy<T extends object>(path: string, factory: RpcProxyFactory<T>): RpcProxy<T> {
46
+ return this.remoteConnectionProvider.createProxy(path, factory);
171
47
  }
172
48
  }
173
-
@@ -0,0 +1,210 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2023 STMicroelectronics and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { AbstractChannel, Channel, Disposable, DisposableCollection, Emitter, Event, servicesPath } from '../../common';
18
+ import { ConnectionSource } from './connection-source';
19
+ import { Socket, io } from 'socket.io-client';
20
+ import { Endpoint } from '../endpoint';
21
+ import { ForwardingChannel } from '../../common/message-rpc/channel';
22
+ import { Uint8ArrayReadBuffer, Uint8ArrayWriteBuffer } from '../../common/message-rpc/uint8-array-message-buffer';
23
+ import { inject, injectable, postConstruct } from 'inversify';
24
+ import { FrontendIdProvider } from './frontend-id-provider';
25
+ import { FrontendApplicationConfigProvider } from '../frontend-application-config-provider';
26
+ import { SocketWriteBuffer } from '../../common/messaging/socket-write-buffer';
27
+ import { ConnectionManagementMessages } from '../../common/messaging/connection-management';
28
+
29
+ @injectable()
30
+ export class WebSocketConnectionSource implements ConnectionSource {
31
+ static readonly NO_CONNECTION = '<none>';
32
+
33
+ @inject(FrontendIdProvider)
34
+ protected readonly frontendIdProvider: FrontendIdProvider;
35
+
36
+ private readonly writeBuffer = new SocketWriteBuffer();
37
+
38
+ private _socket: Socket;
39
+ get socket(): Socket {
40
+ return this._socket;
41
+ }
42
+
43
+ protected currentChannel: AbstractChannel;
44
+
45
+ protected readonly onConnectionDidOpenEmitter: Emitter<Channel> = new Emitter();
46
+ get onConnectionDidOpen(): Event<Channel> {
47
+ return this.onConnectionDidOpenEmitter.event;
48
+ }
49
+
50
+ protected readonly onSocketDidOpenEmitter: Emitter<void> = new Emitter();
51
+ get onSocketDidOpen(): Event<void> {
52
+ return this.onSocketDidOpenEmitter.event;
53
+ }
54
+
55
+ protected readonly onSocketDidCloseEmitter: Emitter<void> = new Emitter();
56
+ get onSocketDidClose(): Event<void> {
57
+ return this.onSocketDidCloseEmitter.event;
58
+ }
59
+
60
+ protected readonly onIncomingMessageActivityEmitter: Emitter<void> = new Emitter();
61
+ get onIncomingMessageActivity(): Event<void> {
62
+ return this.onIncomingMessageActivityEmitter.event;
63
+ }
64
+
65
+ constructor() {
66
+ }
67
+
68
+ @postConstruct()
69
+ openSocket(): void {
70
+ const url = this.createWebSocketUrl(servicesPath);
71
+ this._socket = this.createWebSocket(url);
72
+
73
+ this._socket.on('connect', () => {
74
+ this.onSocketDidOpenEmitter.fire();
75
+ this.handleSocketConnected();
76
+ });
77
+
78
+ this._socket.on('disconnect', () => {
79
+ this.onSocketDidCloseEmitter.fire();
80
+ });
81
+
82
+ this._socket.on('error', reason => {
83
+ if (this.currentChannel) {
84
+ this.currentChannel.onErrorEmitter.fire(reason);
85
+ };
86
+ });
87
+ this._socket.connect();
88
+ }
89
+
90
+ protected handleSocketConnected(): void {
91
+ if (this.currentChannel) {
92
+ const reconnectListener = (hasConnection: boolean) => {
93
+ this._socket.off(ConnectionManagementMessages.RECONNECT, reconnectListener);
94
+ if (hasConnection) {
95
+ this.writeBuffer.flush(this.socket);
96
+ } else {
97
+ if (FrontendApplicationConfigProvider.get().reloadOnReconnect) {
98
+ window.location.reload(); // this might happen in the preload module, when we have no window service yet
99
+ } else {
100
+ this.connectNewChannel();
101
+ }
102
+ }
103
+ };
104
+ this._socket.on(ConnectionManagementMessages.RECONNECT, reconnectListener);
105
+ this._socket.emit(ConnectionManagementMessages.RECONNECT, this.frontendIdProvider.getId());
106
+ } else {
107
+ const initialConnectListener = () => {
108
+ this._socket.off(ConnectionManagementMessages.INITIAL_CONNECT, initialConnectListener);
109
+ this.connectNewChannel();
110
+ };
111
+ this._socket.on(ConnectionManagementMessages.INITIAL_CONNECT, initialConnectListener);
112
+ this._socket.emit(ConnectionManagementMessages.INITIAL_CONNECT, this.frontendIdProvider.getId());
113
+ }
114
+ }
115
+
116
+ connectNewChannel(): void {
117
+ if (this.currentChannel) {
118
+ this.writeBuffer.drain();
119
+ this.currentChannel.close();
120
+ this.currentChannel.onCloseEmitter.fire({ reason: 'reconnecting channel' });
121
+ }
122
+ this.currentChannel = this.createChannel();
123
+ this.onConnectionDidOpenEmitter.fire(this.currentChannel);
124
+ }
125
+
126
+ protected createChannel(): AbstractChannel {
127
+ const toDispose = new DisposableCollection();
128
+
129
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
130
+ const messageHandler = (data: any) => {
131
+ this.onIncomingMessageActivityEmitter.fire();
132
+ if (this.currentChannel) {
133
+ // In the browser context socketIO receives binary messages as ArrayBuffers.
134
+ // So we have to convert them to a Uint8Array before delegating the message to the read buffer.
135
+ const buffer = data instanceof ArrayBuffer ? new Uint8Array(data) : data;
136
+ this.currentChannel.onMessageEmitter.fire(() => new Uint8ArrayReadBuffer(buffer));
137
+ };
138
+ };
139
+ this._socket.on('message', messageHandler);
140
+ toDispose.push(Disposable.create(() => {
141
+ this.socket.off('message', messageHandler);
142
+ }));
143
+
144
+ const channel = new ForwardingChannel('any', () => {
145
+ toDispose.dispose();
146
+ }, () => {
147
+ const result = new Uint8ArrayWriteBuffer();
148
+
149
+ result.onCommit(buffer => {
150
+ if (this.socket.connected) {
151
+ this.socket.send(buffer);
152
+ } else {
153
+ this.writeBuffer.buffer(buffer);
154
+ }
155
+ });
156
+
157
+ return result;
158
+ });
159
+ return channel;
160
+ }
161
+
162
+ /**
163
+ * @param path The handler to reach in the backend.
164
+ */
165
+ protected createWebSocketUrl(path: string): string {
166
+ // Since we are using Socket.io, the path should look like the following:
167
+ // proto://domain.com/{path}
168
+ return this.createEndpoint(path).getWebSocketUrl().withPath(path).toString();
169
+ }
170
+
171
+ protected createHttpWebSocketUrl(path: string): string {
172
+ return this.createEndpoint(path).getRestUrl().toString();
173
+ }
174
+
175
+ protected createEndpoint(path: string): Endpoint {
176
+ return new Endpoint({ path });
177
+ }
178
+
179
+ /**
180
+ * Creates a web socket for the given url
181
+ */
182
+ protected createWebSocket(url: string): Socket {
183
+ return io(url, {
184
+ path: this.createSocketIoPath(url),
185
+ reconnection: true,
186
+ reconnectionDelay: 1000,
187
+ reconnectionDelayMax: 10000,
188
+ reconnectionAttempts: Infinity,
189
+ extraHeaders: {
190
+ // Socket.io strips the `origin` header
191
+ // We need to provide our own for validation
192
+ 'fix-origin': window.location.origin
193
+ }
194
+ });
195
+ }
196
+
197
+ /**
198
+ * Path for Socket.io to make its requests to.
199
+ */
200
+ protected createSocketIoPath(url: string): string | undefined {
201
+ if (location.protocol === Endpoint.PROTO_FILE) {
202
+ return '/socket.io';
203
+ }
204
+ let { pathname } = location;
205
+ if (!pathname.endsWith('/')) {
206
+ pathname += '/';
207
+ }
208
+ return pathname + 'socket.io';
209
+ }
210
+ }
@@ -33,7 +33,7 @@ export class I18nPreloadContribution implements PreloadContribution {
33
33
  locale: defaultLocale
34
34
  });
35
35
  }
36
- if (nls.locale) {
36
+ if (nls.locale && nls.locale !== nls.defaultLocale) {
37
37
  const localization = await this.localizationServer.loadLocalization(nls.locale);
38
38
  if (localization.languagePack) {
39
39
  nls.localization = localization;
@@ -2101,7 +2101,7 @@ export namespace ApplicationShell {
2101
2101
 
2102
2102
  export const areaLabels: Record<Area, string> = {
2103
2103
  main: nls.localizeByDefault('Main'),
2104
- top: nls.localize('theia/shell-area/top', 'Top'),
2104
+ top: nls.localizeByDefault('Top'),
2105
2105
  left: nls.localizeByDefault('Left'),
2106
2106
  right: nls.localizeByDefault('Right'),
2107
2107
  bottom: nls.localizeByDefault('Bottom'),
@@ -58,6 +58,12 @@ export class CompressedTreeWidget extends TreeViewWelcomeWidget {
58
58
  }
59
59
  }
60
60
 
61
+ protected override shouldRenderIndent(node: TreeNode): boolean {
62
+ return !this.compressionToggle.compress
63
+ || !this.compressionService.isCompressionParticipant(node)
64
+ || this.compressionService.getCompressionHead(node) === node;
65
+ }
66
+
61
67
  protected override shouldDisplayNode(node: TreeNode): boolean {
62
68
  if (this.compressionToggle.compress && this.compressionService.isCompressionParticipant(node) && !this.compressionService.isCompressionHead(node)) {
63
69
  return false;
@@ -66,14 +72,18 @@ export class CompressedTreeWidget extends TreeViewWelcomeWidget {
66
72
  }
67
73
 
68
74
  protected override getDepthForNode(node: TreeNode, depths: Map<CompositeTreeNode | undefined, number>): number {
69
- if (!this.compressionToggle.compress) { return super.getDepthForNode(node, depths); }
75
+ if (!this.compressionToggle.compress) {
76
+ return super.getDepthForNode(node, depths);
77
+ }
70
78
  const parent = this.compressionService.getCompressionHead(node.parent) ?? node.parent;
71
79
  const parentDepth = depths.get(parent);
72
80
  return parentDepth === undefined ? 0 : TreeNode.isVisible(node.parent) ? parentDepth + 1 : parentDepth;
73
81
  }
74
82
 
75
83
  protected override toNodeRow(node: TreeNode, index: number, depth: number): CompressedNodeRow {
76
- if (!this.compressionToggle.compress) { return super.toNodeRow(node, index, depth); }
84
+ if (!this.compressionToggle.compress) {
85
+ return super.toNodeRow(node, index, depth);
86
+ }
77
87
  const row: CompressedNodeRow = { node, index, depth };
78
88
  if (this.compressionService.isCompressionHead(node)) {
79
89
  row.compressionChain = this.compressionService.getCompressionChain(node);
@@ -102,7 +112,9 @@ export class CompressedTreeWidget extends TreeViewWelcomeWidget {
102
112
  }
103
113
 
104
114
  protected override getCaptionChildren(node: TreeNode, props: CompressedNodeProps): React.ReactNode {
105
- if (!this.compressionToggle.compress || !props.compressionChain) { return super.getCaptionChildren(node, props); }
115
+ if (!this.compressionToggle.compress || !props.compressionChain) {
116
+ return super.getCaptionChildren(node, props);
117
+ }
106
118
  return props.compressionChain.map((subNode, index, self) => {
107
119
  const classes = ['theia-tree-compressed-label-part'];
108
120
  if (SelectableTreeNode.isSelected(subNode)) {
@@ -129,21 +141,27 @@ export class CompressedTreeWidget extends TreeViewWelcomeWidget {
129
141
  }
130
142
 
131
143
  protected override handleUp(event: KeyboardEvent): void {
132
- if (!this.compressionToggle.compress) { return super.handleUp(event); }
144
+ if (!this.compressionToggle.compress) {
145
+ return super.handleUp(event);
146
+ }
133
147
  const type = this.props.multiSelect && this.hasShiftMask(event) ? TreeSelection.SelectionType.RANGE : undefined;
134
148
  this.model.selectPrevRow(type);
135
149
  this.node.focus();
136
150
  }
137
151
 
138
152
  protected override handleDown(event: KeyboardEvent): void {
139
- if (!this.compressionToggle.compress) { return super.handleDown(event); }
153
+ if (!this.compressionToggle.compress) {
154
+ return super.handleDown(event);
155
+ }
140
156
  const type = this.props.multiSelect && this.hasShiftMask(event) ? TreeSelection.SelectionType.RANGE : undefined;
141
157
  this.model.selectNextRow(type);
142
158
  this.node.focus();
143
159
  }
144
160
 
145
161
  protected override async handleLeft(event: KeyboardEvent): Promise<void> {
146
- if (!this.compressionToggle.compress) { return super.handleLeft(event); }
162
+ if (!this.compressionToggle.compress) {
163
+ return super.handleLeft(event);
164
+ }
147
165
  if (Boolean(this.props.multiSelect) && (this.hasCtrlCmdMask(event) || this.hasShiftMask(event))) {
148
166
  return;
149
167
  }
@@ -160,7 +178,9 @@ export class CompressedTreeWidget extends TreeViewWelcomeWidget {
160
178
  }
161
179
 
162
180
  protected override async handleRight(event: KeyboardEvent): Promise<void> {
163
- if (!this.compressionToggle.compress) { return super.handleRight(event); }
181
+ if (!this.compressionToggle.compress) {
182
+ return super.handleRight(event);
183
+ }
164
184
  if (Boolean(this.props.multiSelect) && (this.hasCtrlCmdMask(event) || this.hasShiftMask(event))) {
165
185
  return;
166
186
  }
@@ -894,22 +894,33 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {
894
894
  let current: TreeNode | undefined = node;
895
895
  let depth = props.depth;
896
896
  while (current && depth) {
897
- const classNames: string[] = [TREE_NODE_INDENT_GUIDE_CLASS];
898
- if (this.needsActiveIndentGuideline(current)) {
899
- classNames.push('active');
900
- } else {
901
- classNames.push(renderIndentGuides === 'onHover' ? 'hover' : 'always');
897
+ if (this.shouldRenderIndent(current)) {
898
+ const classNames: string[] = [TREE_NODE_INDENT_GUIDE_CLASS];
899
+ if (this.needsActiveIndentGuideline(current)) {
900
+ classNames.push('active');
901
+ } else {
902
+ classNames.push(renderIndentGuides === 'onHover' ? 'hover' : 'always');
903
+ }
904
+ const paddingLeft = this.getDepthPadding(depth);
905
+ indentDivs.unshift(<div key={depth} className={classNames.join(' ')} style={{
906
+ paddingLeft: `${paddingLeft}px`
907
+ }} />);
908
+ depth--;
902
909
  }
903
- const paddingLeft = this.getDepthPadding(depth);
904
- indentDivs.unshift(<div key={depth} className={classNames.join(' ')} style={{
905
- paddingLeft: `${paddingLeft}px`
906
- }} />);
907
910
  current = current.parent;
908
- depth--;
909
911
  }
910
912
  return indentDivs;
911
913
  }
912
914
 
915
+ /**
916
+ * Determines whether an indentation div should be rendered for the specified tree node.
917
+ * If there are multiple tree nodes inside of a single rendered row,
918
+ * this method should only return true for the first node.
919
+ */
920
+ protected shouldRenderIndent(node: TreeNode): boolean {
921
+ return true;
922
+ }
923
+
913
924
  protected needsActiveIndentGuideline(node: TreeNode): boolean {
914
925
  const parent = node.parent;
915
926
  if (!parent || !this.isExpandable(parent)) {