|
| 1 | +import { IdeClient } from "@coder/ide"; |
1 | 2 | import * as paths from "./fill/paths";
|
2 |
| -import "./fill/platform"; |
3 |
| -import "./fill/storageDatabase"; |
4 |
| -import "./fill/windowsService"; |
5 |
| -import "./fill/workspacesService"; |
6 |
| -import "./fill/environmentService"; |
7 |
| -import "./fill/vscodeTextmate"; |
8 |
| -import "./fill/codeEditor"; |
9 |
| -import "./fill/mouseEvent"; |
10 |
| -import "./fill/menuRegistry"; |
11 |
| -import "./fill/workbenchRegistry"; |
12 |
| -import { PasteAction } from "./fill/paste"; |
13 |
| -import "./fill/dom"; |
14 | 3 | import "./vscode.scss";
|
15 |
| -import { IdeClient, IProgress, INotificationHandle } from "@coder/ide"; |
16 |
| -import { registerContextMenuListener } from "vs/base/parts/contextmenu/electron-main/contextmenu"; |
17 |
| -import { LogLevel } from "vs/platform/log/common/log"; |
18 |
| -import { URI } from "vs/base/common/uri"; |
19 |
| -import { INotificationService } from "vs/platform/notification/common/notification"; |
20 |
| -import { IProgressService2, ProgressLocation } from "vs/platform/progress/common/progress"; |
21 |
| -import { ExplorerItem, ExplorerModel } from "vs/workbench/parts/files/common/explorerModel"; |
22 |
| -import { DragMouseEvent } from "vs/base/browser/mouseEvent"; |
23 |
| -import { IEditorService, IResourceEditor } from "vs/workbench/services/editor/common/editorService"; |
24 |
| -import { IEditorGroup } from "vs/workbench/services/group/common/editorGroupsService"; |
25 |
| -import { IWindowsService, IWindowConfiguration } from "vs/platform/windows/common/windows"; |
26 |
| -import { ServiceCollection } from "vs/platform/instantiation/common/serviceCollection"; |
27 |
| -import { RawContextKey, IContextKeyService } from "vs/platform/contextkey/common/contextkey"; |
28 |
| -import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from "vs/platform/workspaces/common/workspaces"; |
29 |
| - |
30 |
| -export class Client extends IdeClient { |
31 |
| - private readonly windowId = parseInt(new Date().toISOString().replace(/[-:.TZ]/g, ""), 10); |
32 |
| - private _serviceCollection: ServiceCollection | undefined; |
33 |
| - private _clipboardContextKey: RawContextKey<boolean> | undefined; |
34 |
| - private _builtInExtensionsDirectory: string | undefined; |
35 |
| - |
36 |
| - public get builtInExtensionsDirectory(): string { |
37 |
| - if (!this._builtInExtensionsDirectory) { |
38 |
| - throw new Error("trying to access builtin extensions directory before it has been set"); |
39 |
| - } |
40 |
| - |
41 |
| - return this._builtInExtensionsDirectory; |
42 |
| - } |
43 |
| - |
44 |
| - public async handleExternalDrop(target: ExplorerItem | ExplorerModel, originalEvent: DragEvent): Promise<void> { |
45 |
| - await this.upload.uploadDropped( |
46 |
| - originalEvent, |
47 |
| - (target instanceof ExplorerItem ? target : target.roots[0]).resource, |
48 |
| - ); |
49 |
| - } |
50 |
| - |
51 |
| - public handleDrop(event: DragEvent, resolveTargetGroup: () => IEditorGroup, afterDrop: (targetGroup: IEditorGroup) => void, targetIndex?: number): void { |
52 |
| - this.initData.then((d) => { |
53 |
| - this.upload.uploadDropped(event, URI.file(d.workingDirectory)).then((paths) => { |
54 |
| - const uris = paths.map((p) => URI.file(p)); |
55 |
| - if (uris.length) { |
56 |
| - (this.serviceCollection.get(IWindowsService) as IWindowsService).addRecentlyOpened(uris); |
57 |
| - } |
58 |
| - |
59 |
| - const editors: IResourceEditor[] = uris.map(uri => ({ |
60 |
| - resource: uri, |
61 |
| - options: { |
62 |
| - pinned: true, |
63 |
| - index: targetIndex, |
64 |
| - }, |
65 |
| - })); |
66 |
| - |
67 |
| - const targetGroup = resolveTargetGroup(); |
68 |
| - |
69 |
| - (this.serviceCollection.get(IEditorService) as IEditorService).openEditors(editors, targetGroup).then(() => { |
70 |
| - afterDrop(targetGroup); |
71 |
| - }); |
72 |
| - }); |
73 |
| - }); |
74 |
| - } |
75 |
| - |
76 |
| - /** |
77 |
| - * Use to toggle the paste option inside editors based on the native clipboard. |
78 |
| - */ |
79 |
| - public get clipboardContextKey(): RawContextKey<boolean> { |
80 |
| - if (!this._clipboardContextKey) { |
81 |
| - throw new Error("Trying to access clipboard context key before it has been set"); |
82 |
| - } |
83 |
| - |
84 |
| - return this._clipboardContextKey; |
85 |
| - } |
86 |
| - |
87 |
| - public get clipboardText(): Promise<string> { |
88 |
| - return this.clipboard.readText(); |
89 |
| - } |
90 |
| - |
91 |
| - /** |
92 |
| - * Create a paste action for use in text inputs. |
93 |
| - */ |
94 |
| - public get pasteAction(): PasteAction { |
95 |
| - return new PasteAction(); |
96 |
| - } |
97 |
| - |
98 |
| - public set workspace(ws: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | undefined) { |
99 |
| - if (typeof ws === "undefined") { |
100 |
| - window.localStorage.removeItem("workspace"); |
101 |
| - } else { |
102 |
| - window.localStorage.setItem("workspace", JSON.stringify(ws)); |
103 |
| - } |
104 |
| - |
105 |
| - location.reload(); |
106 |
| - } |
107 |
| - |
108 |
| - public get workspace(): undefined | IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier { |
109 |
| - const ws = window.localStorage.getItem("workspace"); |
110 |
| - try { |
111 |
| - return JSON.parse(ws!); |
112 |
| - } catch (ex) { |
113 |
| - return undefined; |
114 |
| - } |
115 |
| - } |
116 |
| - |
117 |
| - public get serviceCollection(): ServiceCollection { |
118 |
| - if (!this._serviceCollection) { |
119 |
| - throw new Error("Trying to access service collection before it has been set"); |
120 |
| - } |
121 |
| - |
122 |
| - return this._serviceCollection; |
123 |
| - } |
124 |
| - |
125 |
| - public set serviceCollection(collection: ServiceCollection) { |
126 |
| - this._serviceCollection = collection; |
127 |
| - this.progressService = { |
128 |
| - start: <T>(title: string, task: (progress: IProgress) => Promise<T>, onCancel: () => void): Promise<T> => { |
129 |
| - let lastProgress = 0; |
130 |
| - |
131 |
| - return (this.serviceCollection.get(IProgressService2) as IProgressService2).withProgress({ |
132 |
| - location: ProgressLocation.Notification, |
133 |
| - title, |
134 |
| - cancellable: true, |
135 |
| - }, (progress) => { |
136 |
| - return task({ |
137 |
| - report: (p): void => { |
138 |
| - progress.report({ increment: p - lastProgress }); |
139 |
| - lastProgress = p; |
140 |
| - }, |
141 |
| - }); |
142 |
| - }, () => { |
143 |
| - onCancel(); |
144 |
| - }); |
145 |
| - }, |
146 |
| - }; |
147 |
| - |
148 |
| - this.notificationService = { |
149 |
| - error: (error: Error): void => (this.serviceCollection.get(INotificationService) as INotificationService).error(error), |
150 |
| - prompt: (severity, message, buttons, onCancel): INotificationHandle => { |
151 |
| - const handle = (this.serviceCollection.get(INotificationService) as INotificationService).prompt( |
152 |
| - severity, message, buttons, { onCancel }, |
153 |
| - ); |
154 |
| - |
155 |
| - return { |
156 |
| - close: (): void => handle.close(), |
157 |
| - updateMessage: (message): void => handle.updateMessage(message), |
158 |
| - updateButtons: (buttons): void => handle.updateActions({ |
159 |
| - primary: buttons.map((button) => ({ |
160 |
| - id: "", |
161 |
| - label: button.label, |
162 |
| - tooltip: "", |
163 |
| - class: undefined, |
164 |
| - enabled: true, |
165 |
| - checked: false, |
166 |
| - radio: false, |
167 |
| - dispose: (): void => undefined, |
168 |
| - run: (): Promise<void> => Promise.resolve(button.run()), |
169 |
| - })), |
170 |
| - }), |
171 |
| - }; |
172 |
| - }, |
173 |
| - }; |
174 |
| - } |
| 4 | +// NOTE: shouldn't import anything from VS Code here or anything that will |
| 5 | +// depend on a synchronous fill like `os`. |
175 | 6 |
|
| 7 | +class VSClient extends IdeClient { |
176 | 8 | protected initialize(): Promise<void> {
|
177 |
| - registerContextMenuListener(); |
178 |
| - |
179 |
| - this._clipboardContextKey = new RawContextKey("nativeClipboard", this.clipboard.isEnabled); |
180 |
| - |
181 | 9 | return this.task("Start workbench", 1000, async (data, sharedData) => {
|
182 | 10 | paths._paths.initialize(data, sharedData);
|
183 |
| - this._builtInExtensionsDirectory = data.builtInExtensionsDirectory; |
184 | 11 | process.env.SHELL = data.shell;
|
185 |
| - |
186 |
| - const workspace = this.workspace || URI.file(data.workingDirectory); |
187 |
| - const { startup } = require("./startup") as typeof import("vs/workbench/electron-browser/main"); |
188 |
| - const config: IWindowConfiguration = { |
189 |
| - machineId: "1", |
190 |
| - windowId: this.windowId, |
191 |
| - logLevel: LogLevel.Info, |
192 |
| - mainPid: 1, |
193 |
| - appRoot: data.dataDirectory, |
194 |
| - execPath: data.tmpDirectory, |
195 |
| - userEnv: {}, |
196 |
| - nodeCachedDataDir: data.tmpDirectory, |
197 |
| - perfEntries: [], |
198 |
| - _: [], |
199 |
| - }; |
200 |
| - if ((workspace as IWorkspaceIdentifier).configPath) { |
201 |
| - config.workspace = workspace as IWorkspaceIdentifier; |
202 |
| - } else { |
203 |
| - config.folderUri = workspace as URI; |
204 |
| - } |
205 |
| - await startup(config); |
206 |
| - const contextKeys = this.serviceCollection.get(IContextKeyService) as IContextKeyService; |
207 |
| - const bounded = this.clipboardContextKey.bindTo(contextKeys); |
208 |
| - this.clipboard.onPermissionChange((enabled) => { |
209 |
| - bounded.set(enabled); |
210 |
| - }); |
211 |
| - this.clipboard.initialize(); |
| 12 | + // At this point everything should be filled, including `os`. `os` also |
| 13 | + // relies on `initData` but it listens first so it initialize before this |
| 14 | + // callback, meaning we are safe to include everything from VS Code now. |
| 15 | + const { workbench } = require("./workbench") as typeof import("./workbench"); |
| 16 | + await workbench.initialize(); |
212 | 17 | }, this.initData, this.sharedProcessData);
|
213 | 18 | }
|
214 | 19 | }
|
215 | 20 |
|
216 |
| -export const client = new Client(); |
| 21 | +export const client = new VSClient(); |
0 commit comments