2019-01-18 21:46:40 +00:00
|
|
|
import "./fill/require";
|
2019-01-22 18:27:59 +00:00
|
|
|
import * as paths from "./fill/paths";
|
2019-01-18 21:46:40 +00:00
|
|
|
import "./fill/storageDatabase";
|
|
|
|
import "./fill/windowsService";
|
2019-01-22 18:27:59 +00:00
|
|
|
import "./fill/environmentService";
|
2019-01-28 17:14:06 +00:00
|
|
|
import "./fill/vscodeTextmate";
|
2019-01-19 00:04:24 +00:00
|
|
|
import "./fill/dom";
|
|
|
|
import "./vscode.scss";
|
2019-01-30 21:40:01 +00:00
|
|
|
import { Client as IDEClient, IURI, IURIFactory, IProgress, INotificationHandle } from "@coder/ide";
|
2019-01-18 21:46:40 +00:00
|
|
|
import { registerContextMenuListener } from "vs/base/parts/contextmenu/electron-main/contextmenu";
|
|
|
|
import { LogLevel } from "vs/platform/log/common/log";
|
|
|
|
import { URI } from "vs/base/common/uri";
|
2019-01-30 21:40:01 +00:00
|
|
|
import { INotificationService } from "vs/platform/notification/common/notification";
|
|
|
|
import { IProgressService2, ProgressLocation } from "vs/platform/progress/common/progress";
|
|
|
|
import { ExplorerItem, Model } from "vs/workbench/parts/files/common/explorerModel";
|
|
|
|
import { DragMouseEvent } from "vs/base/browser/mouseEvent";
|
|
|
|
import { IEditorService, IResourceEditor } from "vs/workbench/services/editor/common/editorService";
|
|
|
|
import { IEditorGroup } from "vs/workbench/services/group/common/editorGroupsService";
|
|
|
|
import { IWindowsService } from "vs/platform/windows/common/windows";
|
|
|
|
import { ServiceCollection } from "vs/platform/instantiation/common/serviceCollection";
|
2019-01-30 22:57:22 +00:00
|
|
|
import { RawContextKey, IContextKeyService } from "vs/platform/contextkey/common/contextkey";
|
|
|
|
import { Action } from "vs/base/common/actions";
|
|
|
|
import * as nls from "vs/nls";
|
2019-01-18 21:46:40 +00:00
|
|
|
|
|
|
|
export class Client extends IDEClient {
|
|
|
|
|
2019-01-30 19:27:21 +00:00
|
|
|
private readonly windowId = parseInt(new Date().toISOString().replace(/[-:.TZ]/g, ""), 10);
|
2019-01-30 21:40:01 +00:00
|
|
|
private _serviceCollection: ServiceCollection | undefined;
|
2019-01-30 22:57:22 +00:00
|
|
|
private _clipboardContextKey: RawContextKey<boolean> | undefined;
|
2019-01-30 21:40:01 +00:00
|
|
|
|
|
|
|
public async handleExternalDrop(target: ExplorerItem | Model, originalEvent: DragMouseEvent): Promise<void> {
|
|
|
|
await this.upload.uploadDropped(
|
|
|
|
originalEvent.browserEvent as DragEvent,
|
|
|
|
(target instanceof ExplorerItem ? target : target.roots[0]).resource,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
public handleDrop(event: DragEvent, resolveTargetGroup: () => IEditorGroup, afterDrop: (targetGroup: IEditorGroup) => void, targetIndex?: number): void {
|
|
|
|
this.initData.then((d) => {
|
|
|
|
this.upload.uploadDropped(event, URI.file(d.workingDirectory)).then((paths) => {
|
|
|
|
const uris = paths.map((p) => URI.file(p));
|
|
|
|
if (uris.length) {
|
|
|
|
(this.serviceCollection.get(IWindowsService) as IWindowsService).addRecentlyOpened(uris);
|
|
|
|
}
|
|
|
|
|
|
|
|
const editors: IResourceEditor[] = uris.map(uri => ({
|
|
|
|
resource: uri,
|
|
|
|
options: {
|
|
|
|
pinned: true,
|
|
|
|
index: targetIndex,
|
|
|
|
},
|
|
|
|
}));
|
|
|
|
|
|
|
|
const targetGroup = resolveTargetGroup();
|
|
|
|
|
|
|
|
(this.serviceCollection.get(IEditorService) as IEditorService).openEditors(editors, targetGroup).then(() => {
|
|
|
|
afterDrop(targetGroup);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-01-30 22:57:22 +00:00
|
|
|
/**
|
|
|
|
* Use to toggle the paste option inside editors based on the native clipboard.
|
|
|
|
*/
|
|
|
|
public get clipboardContextKey(): RawContextKey<boolean> {
|
|
|
|
if (!this._clipboardContextKey) {
|
|
|
|
throw new Error("Trying to access clipboard context key before it has been set");
|
|
|
|
}
|
|
|
|
|
|
|
|
return this._clipboardContextKey;
|
|
|
|
}
|
|
|
|
|
|
|
|
public get clipboardText(): Promise<string> {
|
|
|
|
return this.clipboard.readText();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a paste action for use in text inputs.
|
|
|
|
*/
|
|
|
|
public get pasteAction(): Action {
|
|
|
|
const getLabel = (enabled: boolean): string => {
|
|
|
|
return enabled
|
|
|
|
? nls.localize("paste", "Paste")
|
|
|
|
: nls.localize("pasteWithKeybind", "Paste (must use keybind)");
|
|
|
|
};
|
|
|
|
|
|
|
|
const pasteAction = new Action(
|
|
|
|
"editor.action.clipboardPasteAction",
|
|
|
|
getLabel(this.clipboard.isEnabled),
|
|
|
|
undefined,
|
|
|
|
this.clipboard.isEnabled,
|
|
|
|
async (): Promise<boolean> => this.clipboard.paste(),
|
|
|
|
);
|
|
|
|
|
|
|
|
this.clipboard.onPermissionChange((enabled) => {
|
|
|
|
pasteAction.label = getLabel(enabled);
|
|
|
|
pasteAction.enabled = enabled;
|
|
|
|
});
|
|
|
|
|
|
|
|
return pasteAction;
|
|
|
|
}
|
|
|
|
|
2019-01-30 21:40:01 +00:00
|
|
|
public get serviceCollection(): ServiceCollection {
|
|
|
|
if (!this._serviceCollection) {
|
|
|
|
throw new Error("Trying to access service collection before it has been set");
|
|
|
|
}
|
|
|
|
|
|
|
|
return this._serviceCollection;
|
|
|
|
}
|
|
|
|
|
|
|
|
public set serviceCollection(collection: ServiceCollection) {
|
|
|
|
this._serviceCollection = collection;
|
|
|
|
this.progressService = {
|
|
|
|
start: <T>(title: string, task: (progress: IProgress) => Promise<T>, onCancel: () => void): Promise<T> => {
|
|
|
|
let lastProgress = 0;
|
|
|
|
|
|
|
|
return (this.serviceCollection.get(IProgressService2) as IProgressService2).withProgress({
|
|
|
|
location: ProgressLocation.Notification,
|
|
|
|
title,
|
|
|
|
cancellable: true,
|
|
|
|
}, (progress) => {
|
|
|
|
return task({
|
|
|
|
report: (p): void => {
|
|
|
|
progress.report({ increment: p - lastProgress });
|
|
|
|
lastProgress = p;
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}, () => {
|
|
|
|
onCancel();
|
|
|
|
});
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
this.notificationService = {
|
|
|
|
error: (error: Error): void => (this.serviceCollection.get(INotificationService) as INotificationService).error(error),
|
|
|
|
prompt: (severity, message, buttons, onCancel): INotificationHandle => {
|
|
|
|
const handle = (this.serviceCollection.get(INotificationService) as INotificationService).prompt(
|
|
|
|
severity, message, buttons, { onCancel },
|
|
|
|
);
|
|
|
|
|
|
|
|
return {
|
|
|
|
close: (): void => handle.close(),
|
|
|
|
updateMessage: (message): void => handle.updateMessage(message),
|
|
|
|
updateButtons: (buttons): void => handle.updateActions({
|
|
|
|
primary: buttons.map((button) => ({
|
|
|
|
id: "",
|
|
|
|
label: button.label,
|
|
|
|
tooltip: "",
|
|
|
|
class: undefined,
|
|
|
|
enabled: true,
|
|
|
|
checked: false,
|
|
|
|
radio: false,
|
|
|
|
dispose: (): void => undefined,
|
|
|
|
run: (): Promise<void> => Promise.resolve(button.run()),
|
|
|
|
})),
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
},
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
protected createUriFactory(): IURIFactory {
|
|
|
|
return {
|
|
|
|
// TODO: not sure why this is an error.
|
|
|
|
// tslint:disable-next-line no-any
|
|
|
|
create: <URI>(uri: IURI): URI => URI.from(uri) as any,
|
|
|
|
file: (path: string): IURI => URI.file(path),
|
|
|
|
parse: (raw: string): IURI => URI.parse(raw),
|
|
|
|
};
|
|
|
|
}
|
2019-01-19 00:04:24 +00:00
|
|
|
|
2019-01-30 19:13:04 +00:00
|
|
|
protected initialize(): Promise<void> {
|
|
|
|
registerContextMenuListener();
|
2019-01-18 21:46:40 +00:00
|
|
|
|
2019-01-30 19:13:04 +00:00
|
|
|
const pathSets = this.sharedProcessData.then((data) => {
|
2019-01-22 18:27:59 +00:00
|
|
|
paths._paths.socketPath = data.socketPath;
|
2019-01-28 17:14:06 +00:00
|
|
|
process.env.VSCODE_LOGS = data.logPath;
|
2019-01-22 18:27:59 +00:00
|
|
|
});
|
2019-01-30 19:13:04 +00:00
|
|
|
|
2019-01-30 22:57:22 +00:00
|
|
|
this._clipboardContextKey = new RawContextKey("nativeClipboard", this.clipboard.isEnabled);
|
|
|
|
|
2019-01-30 19:13:04 +00:00
|
|
|
return this.task("Start workbench", 1000, async (data) => {
|
2019-01-22 18:27:59 +00:00
|
|
|
paths._paths.appData = data.dataDirectory;
|
|
|
|
paths._paths.defaultUserData = data.dataDirectory;
|
2019-01-28 17:14:06 +00:00
|
|
|
process.env.SHELL = data.shell;
|
2019-01-18 21:46:40 +00:00
|
|
|
|
|
|
|
const { startup } = require("./startup");
|
|
|
|
await startup({
|
|
|
|
machineId: "1",
|
|
|
|
windowId: this.windowId,
|
|
|
|
logLevel: LogLevel.Info,
|
|
|
|
mainPid: 1,
|
2019-01-22 18:27:59 +00:00
|
|
|
appRoot: data.dataDirectory,
|
|
|
|
execPath: data.tmpDirectory,
|
2019-01-18 21:46:40 +00:00
|
|
|
userEnv: {},
|
2019-01-22 18:27:59 +00:00
|
|
|
nodeCachedDataDir: data.tmpDirectory,
|
2019-01-18 21:46:40 +00:00
|
|
|
perfEntries: [],
|
|
|
|
_: [],
|
2019-01-28 17:14:06 +00:00
|
|
|
folderUri: URI.file(data.workingDirectory),
|
2019-01-18 21:46:40 +00:00
|
|
|
});
|
|
|
|
|
2019-01-30 22:57:22 +00:00
|
|
|
const contextKeys = this.serviceCollection.get(IContextKeyService) as IContextKeyService;
|
|
|
|
const bounded = this.clipboardContextKey.bindTo(contextKeys);
|
|
|
|
this.clipboard.onPermissionChange((enabled) => {
|
|
|
|
bounded.set(enabled);
|
|
|
|
});
|
2019-01-18 21:46:40 +00:00
|
|
|
this.clipboard.initialize();
|
2019-01-30 19:13:04 +00:00
|
|
|
}, this.initData, pathSets);
|
2019-01-18 21:46:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
export const client = new Client();
|