Featureful (#31)
* Fix loading within the CLI * Remove app * Remove promise handle * Add initial travis file * Add libxkbfile dependency * Add libxkbfile-dev * Add build script * Fix malformed bash statement * Remove yarn from script * Improve build script * Extract upx before usage * Only run upx if on linux * Ensure resource directory exists * Pack runnable binary * Export binary with platform * Improve build process * Install upx before running install script * Update typescript version before running nexe * Add os.release() function for multi-platform support * Update travis.yml to improve deployment * Add on CI * Update to v1.31.0 * Add libsecret * Update build target * Skip cleanup * Fix built-in extensions * Add basics for apps * Create custom DNS server * Fix forking within CLI. Fixes TS language features * Fix filename resolve * Fix default extensions path * Add custom dialog * Store workspace path * Remove outfiles * Cleanup * Always authed outside of CLI * Use location.host for client * Remove useless app interface * Remove debug file for building wordlist * Use chromes tcp host * Update patch * Build browser app before packaging * Replace all css containing file:// URLs, fix webviews * Fix save * Fix mkdir
This commit is contained in:
@ -2,6 +2,7 @@ import * as paths from "./fill/paths";
|
||||
import "./fill/platform";
|
||||
import "./fill/storageDatabase";
|
||||
import "./fill/windowsService";
|
||||
import "./fill/workspacesService";
|
||||
import "./fill/environmentService";
|
||||
import "./fill/vscodeTextmate";
|
||||
import "./fill/codeEditor";
|
||||
@ -17,13 +18,14 @@ import { LogLevel } from "vs/platform/log/common/log";
|
||||
import { URI } from "vs/base/common/uri";
|
||||
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 { ExplorerItem, ExplorerModel } 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 { IWindowsService, IWindowConfiguration } from "vs/platform/windows/common/windows";
|
||||
import { ServiceCollection } from "vs/platform/instantiation/common/serviceCollection";
|
||||
import { RawContextKey, IContextKeyService } from "vs/platform/contextkey/common/contextkey";
|
||||
import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from "vs/platform/workspaces/common/workspaces";
|
||||
|
||||
export class Client extends IdeClient {
|
||||
private readonly windowId = parseInt(new Date().toISOString().replace(/[-:.TZ]/g, ""), 10);
|
||||
@ -39,7 +41,7 @@ export class Client extends IdeClient {
|
||||
return this._builtInExtensionsDirectory;
|
||||
}
|
||||
|
||||
public async handleExternalDrop(target: ExplorerItem | Model, originalEvent: DragMouseEvent): Promise<void> {
|
||||
public async handleExternalDrop(target: ExplorerItem | ExplorerModel, originalEvent: DragMouseEvent): Promise<void> {
|
||||
await this.upload.uploadDropped(
|
||||
originalEvent.browserEvent as DragEvent,
|
||||
(target instanceof ExplorerItem ? target : target.roots[0]).resource,
|
||||
@ -93,6 +95,25 @@ export class Client extends IdeClient {
|
||||
return new PasteAction();
|
||||
}
|
||||
|
||||
public set workspace(ws: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | undefined) {
|
||||
if (typeof ws === "undefined") {
|
||||
window.localStorage.removeItem("workspace");
|
||||
} else {
|
||||
window.localStorage.setItem("workspace", JSON.stringify(ws));
|
||||
}
|
||||
|
||||
location.reload();
|
||||
}
|
||||
|
||||
public get workspace(): undefined | IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier {
|
||||
const ws = window.localStorage.getItem("workspace");
|
||||
try {
|
||||
return JSON.parse(ws!);
|
||||
} catch (ex) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
public get serviceCollection(): ServiceCollection {
|
||||
if (!this._serviceCollection) {
|
||||
throw new Error("Trying to access service collection before it has been set");
|
||||
@ -162,8 +183,9 @@ export class Client extends IdeClient {
|
||||
this._builtInExtensionsDirectory = data.builtInExtensionsDirectory;
|
||||
process.env.SHELL = data.shell;
|
||||
|
||||
const { startup } = require("./startup");
|
||||
await startup({
|
||||
const workspace = this.workspace || URI.file(data.workingDirectory);
|
||||
const { startup } = require("./startup") as typeof import("vs/workbench/electron-browser/main");
|
||||
const config: IWindowConfiguration = {
|
||||
machineId: "1",
|
||||
windowId: this.windowId,
|
||||
logLevel: LogLevel.Info,
|
||||
@ -174,9 +196,13 @@ export class Client extends IdeClient {
|
||||
nodeCachedDataDir: data.tmpDirectory,
|
||||
perfEntries: [],
|
||||
_: [],
|
||||
folderUri: URI.file(data.workingDirectory),
|
||||
});
|
||||
|
||||
};
|
||||
if ((workspace as IWorkspaceIdentifier).configPath) {
|
||||
config.workspace = workspace as IWorkspaceIdentifier;
|
||||
} else {
|
||||
config.folderUri = workspace as URI;
|
||||
}
|
||||
await startup(config);
|
||||
const contextKeys = this.serviceCollection.get(IContextKeyService) as IContextKeyService;
|
||||
const bounded = this.clipboardContextKey.bindTo(contextKeys);
|
||||
this.clipboard.onPermissionChange((enabled) => {
|
||||
|
146
packages/vscode/src/dialog.scss
Normal file
146
packages/vscode/src/dialog.scss
Normal file
@ -0,0 +1,146 @@
|
||||
.dialog {
|
||||
--primary: #2A2E37;
|
||||
--border: black;
|
||||
--faded: #a0a1a5;
|
||||
--header-background: #161616;
|
||||
--header-foreground: white;
|
||||
--list-active-selection-background: rgb(0, 120, 160);
|
||||
--list-active-selection-foreground: white;
|
||||
--list-hover-background: rgb(36, 39, 46);
|
||||
font-family: inherit;
|
||||
box-shadow: 0 18px 80px 10px rgba(0, 0, 0, 0.1);
|
||||
background-color: var(--primary);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
user-select: none;
|
||||
overflow: hidden;
|
||||
border-radius: 5px;
|
||||
|
||||
.monaco-tl-twistie {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.title {
|
||||
background-color: var(--header-background);
|
||||
color: var(--header-foreground);
|
||||
padding: 1px;
|
||||
font-size: 11px;
|
||||
font-weight: normal;
|
||||
text-transform: uppercase;
|
||||
white-space: nowrap;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.nav {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 4px;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
min-height: 32px;
|
||||
}
|
||||
|
||||
.path {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
.path-part {
|
||||
padding: 5px;
|
||||
border-radius: 3px;
|
||||
font-size: 1.2em;
|
||||
cursor: pointer;
|
||||
|
||||
&:not(:first-child) {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
&.active {
|
||||
font-weight: bold;
|
||||
color: var(--list-active-selection-foreground);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.file-area {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.dialog-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 0.2fr 0.8fr;
|
||||
}
|
||||
|
||||
.headings {
|
||||
padding: 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.dialog-entry {
|
||||
cursor: pointer;
|
||||
font-size: 1.2em;
|
||||
padding: 0px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
|
||||
.dialog-entry-info {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.dialog-entry-icon {
|
||||
width: 16px;
|
||||
height: 19px;
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
margin-bottom: -3px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--list-hover-background);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: var(--list-active-selection-background);
|
||||
color: var(--list-active-selection-foreground);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 10px;
|
||||
position: relative;
|
||||
background: var(--primary);
|
||||
border-top: 1px solid var(--border);
|
||||
|
||||
button:first-child {
|
||||
margin-left: auto;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
button {
|
||||
background: transparent;
|
||||
outline: none;
|
||||
border: 0;
|
||||
color: var(--faded);
|
||||
padding: 10px;
|
||||
padding-left: 18px;
|
||||
padding-right: 18px;
|
||||
transition: 150ms background ease, 150ms color ease;
|
||||
cursor: pointer;
|
||||
border-radius: 5px;
|
||||
|
||||
&:hover {
|
||||
background: var(--titlebar);
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.monaco-shell .monaco-tree.focused.no-focused-item:focus:before, .monaco-shell .monaco-list:not(.element-focused):focus:before {
|
||||
display: none;
|
||||
}
|
471
packages/vscode/src/dialog.ts
Normal file
471
packages/vscode/src/dialog.ts
Normal file
@ -0,0 +1,471 @@
|
||||
import { Emitter, Event } from "@coder/events";
|
||||
import { client as ideClient } from "@coder/ide/src/fill/client";
|
||||
import { client } from "@coder/vscode/src/client";
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
import { $, addClass, append } from "vs/base/browser/dom";
|
||||
import { HighlightedLabel } from "vs/base/browser/ui/highlightedlabel/highlightedLabel";
|
||||
import { ObjectTree } from "vs/base/browser/ui/tree/objectTree";
|
||||
import { ITreeElement, ITreeNode, ITreeRenderer, TreeFilterResult, TreeVisibility } from "vs/base/browser/ui/tree/tree";
|
||||
import { KeyCode } from "vs/base/common/keyCodes";
|
||||
import { URI } from "vs/base/common/uri";
|
||||
import { getIconClasses } from "vs/editor/common/services/getIconClasses";
|
||||
import { IModelService } from "vs/editor/common/services/modelService";
|
||||
import { IModeService } from "vs/editor/common/services/modeService";
|
||||
import { FileKind } from "vs/platform/files/common/files";
|
||||
import "./dialog.scss";
|
||||
import { IThemeService } from "vs/platform/theme/common/themeService";
|
||||
|
||||
declare var __non_webpack_require__: typeof require;
|
||||
|
||||
export enum DialogType {
|
||||
NewFolder,
|
||||
Save,
|
||||
Open,
|
||||
}
|
||||
|
||||
export interface CommonDialogOptions {
|
||||
readonly title?: string;
|
||||
readonly defaultPath?: string;
|
||||
readonly buttonLabel?: string;
|
||||
}
|
||||
|
||||
export interface OpenDialogOptions extends CommonDialogOptions {
|
||||
readonly properties: {
|
||||
readonly openFile: true;
|
||||
readonly openDirectory?: boolean;
|
||||
readonly showHiddenFiles?: boolean;
|
||||
} | {
|
||||
readonly openDirectory: true;
|
||||
readonly showHiddenFiles?: boolean;
|
||||
readonly openFile?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export interface SaveDialogOptions extends CommonDialogOptions {
|
||||
readonly type: DialogType.Save;
|
||||
readonly nameFieldLabel?: string;
|
||||
}
|
||||
|
||||
export type DialogOptions = OpenDialogOptions | SaveDialogOptions;
|
||||
|
||||
export const showOpenDialog = (options: OpenDialogOptions): Promise<string> => {
|
||||
return new Promise<string>((resolve, reject): void => {
|
||||
const dialog = new Dialog(DialogType.Open, options);
|
||||
dialog.onSelect((e) => {
|
||||
dialog.dispose();
|
||||
resolve(e);
|
||||
});
|
||||
dialog.onError((e) => {
|
||||
dialog.dispose();
|
||||
reject(e);
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
interface DialogEntry {
|
||||
readonly fullPath: string;
|
||||
readonly name: string;
|
||||
readonly isDirectory: boolean;
|
||||
readonly size: number;
|
||||
readonly lastModified: string;
|
||||
}
|
||||
|
||||
class Dialog {
|
||||
private _path: string | undefined;
|
||||
|
||||
private static readonly UpperDirId = "..";
|
||||
|
||||
private readonly filesNode: HTMLElement;
|
||||
private readonly pathNode: HTMLElement;
|
||||
|
||||
private readonly entryList: ObjectTree<DialogEntry, string>;
|
||||
private readonly background: HTMLElement;
|
||||
private readonly root: HTMLElement;
|
||||
|
||||
private readonly selectEmitter: Emitter<string>;
|
||||
private readonly errorEmitter: Emitter<Error>;
|
||||
|
||||
public constructor(
|
||||
private readonly type: DialogType,
|
||||
private readonly options: DialogOptions,
|
||||
) {
|
||||
this.selectEmitter = new Emitter();
|
||||
this.errorEmitter = new Emitter();
|
||||
|
||||
this.background = document.createElement("div");
|
||||
this.background.style.position = "absolute";
|
||||
this.background.style.top = "0";
|
||||
this.background.style.left = "0";
|
||||
this.background.style.bottom = "0";
|
||||
this.background.style.right = "0";
|
||||
this.background.style.zIndex = "5";
|
||||
this.background.style.display = "flex";
|
||||
this.background.style.alignItems = "center";
|
||||
this.background.style.justifyContent = "center";
|
||||
this.background.style.background = "rgba(0, 0, 0, 0.25)";
|
||||
|
||||
this.root = document.createElement("div");
|
||||
this.root.style.width = "850px";
|
||||
this.root.style.height = "600px";
|
||||
this.background.appendChild(this.root);
|
||||
document.body.appendChild(this.background);
|
||||
this.root.classList.add("dialog");
|
||||
|
||||
const setProperty = (vari: string, id: string): void => {
|
||||
const getColor = (id: string): string | undefined => {
|
||||
const ts = client.serviceCollection.get<IThemeService>(IThemeService) as IThemeService;
|
||||
const c = ts.getTheme().getColor(id);
|
||||
if (!c) {
|
||||
return;
|
||||
}
|
||||
|
||||
return c.toString();
|
||||
};
|
||||
const c = getColor(id);
|
||||
if (c) {
|
||||
this.root.style.setProperty(vari, c);
|
||||
}
|
||||
};
|
||||
setProperty("--primary", "sideBar.background");
|
||||
setProperty("--list-active-selection-background", "list.activeSelectionBackground");
|
||||
setProperty("--list-active-selection-foreground", "list.activeSelectionForeground");
|
||||
setProperty("--list-hover-background", "list.hoverBackground");
|
||||
setProperty("--header-background", "sideBarSectionHeader.background");
|
||||
setProperty("--header-foreground", "sideBarSectionHeader.foreground");
|
||||
setProperty("--border", "panel.border");
|
||||
|
||||
this.background.addEventListener("contextmenu", (event) => {
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
const titleNode = document.createElement("div");
|
||||
titleNode.classList.add("title");
|
||||
let title: string | undefined;
|
||||
switch (this.type) {
|
||||
// case DialogType.NewFolder:
|
||||
// title = "New Folder";
|
||||
// break;
|
||||
case DialogType.Open:
|
||||
title = "Open File";
|
||||
break;
|
||||
case DialogType.Save:
|
||||
title = "Save File";
|
||||
break;
|
||||
default:
|
||||
throw new Error("Uncased type");
|
||||
}
|
||||
titleNode.innerText = options.title || title;
|
||||
this.root.appendChild(titleNode);
|
||||
|
||||
const navItems = document.createElement("div");
|
||||
navItems.classList.add("nav");
|
||||
|
||||
this.pathNode = document.createElement("div");
|
||||
this.pathNode.classList.add("path");
|
||||
navItems.appendChild(this.pathNode);
|
||||
this.root.appendChild(navItems);
|
||||
|
||||
const fileAreaNode = document.createElement("div");
|
||||
fileAreaNode.classList.add("file-area");
|
||||
fileAreaNode.classList.add("show-file-icons");
|
||||
|
||||
const headingsNode = document.createElement("div");
|
||||
headingsNode.className = "headings dialog-grid";
|
||||
["Name", "Size", "Last Modified"].forEach(e => {
|
||||
const header = document.createElement("div");
|
||||
header.innerText = e;
|
||||
headingsNode.appendChild(header);
|
||||
});
|
||||
|
||||
this.filesNode = document.createElement("div");
|
||||
this.filesNode.className = "files-list";
|
||||
fileAreaNode.appendChild(headingsNode);
|
||||
this.entryList = new ObjectTree<DialogEntry, string>(this.filesNode, {
|
||||
getHeight: (entry: DialogEntry): number => {
|
||||
return 20;
|
||||
},
|
||||
getTemplateId: (entry: DialogEntry): string => {
|
||||
return "dialog-entry";
|
||||
},
|
||||
}, [new DialogEntryRenderer()], {
|
||||
openController: {
|
||||
shouldOpen: (event): boolean => {
|
||||
return true;
|
||||
},
|
||||
},
|
||||
keyboardNavigationLabelProvider: {
|
||||
getKeyboardNavigationLabel: (element): string => {
|
||||
return element.name;
|
||||
},
|
||||
mightProducePrintableCharacter: (event): boolean => {
|
||||
if (event.ctrlKey || event.metaKey) {
|
||||
// ignore ctrl/cmd-combination but not shift/alt-combinatios
|
||||
return false;
|
||||
}
|
||||
// weak check for certain ranges. this is properly implemented in a subclass
|
||||
// with access to the KeyboardMapperFactory.
|
||||
if ((event.keyCode >= KeyCode.KEY_A && event.keyCode <= KeyCode.KEY_Z)
|
||||
|| (event.keyCode >= KeyCode.KEY_0 && event.keyCode <= KeyCode.KEY_9)
|
||||
|| event.keyCode === KeyCode.US_DOT || event.keyCode === KeyCode.US_SLASH || event.keyCode === KeyCode.US_MINUS) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
},
|
||||
automaticKeyboardNavigation: true,
|
||||
enableKeyboardNavigation: true,
|
||||
multipleSelectionSupport: false,
|
||||
openOnSingleClick: false,
|
||||
filter: {
|
||||
filter: (): TreeFilterResult<string> => {
|
||||
// tslint:disable-next-line:no-any
|
||||
(<any>this.entryList)._options.simpleKeyboardNavigation = true;
|
||||
// tslint:disable-next-line:no-any
|
||||
const pat = (<any>this.entryList).typeFilterController.filter._pattern;
|
||||
|
||||
return {
|
||||
data: pat,
|
||||
visibility: TreeVisibility.Visible,
|
||||
};
|
||||
},
|
||||
},
|
||||
filterOnType: true,
|
||||
});
|
||||
// tslint:disable-next-line:no-any
|
||||
(<any>this.entryList).focusNavigationFilter = (node: ITreeNode<DialogEntry, string>): boolean => {
|
||||
if (node.filterData) {
|
||||
return node.element.name.toLowerCase().startsWith(node.filterData.toLowerCase()!);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
this.entryList.onDidOpen((event) => {
|
||||
const element = event.elements[0]!;
|
||||
if (!element) {
|
||||
const fv = this.filterValue;
|
||||
|
||||
if (fv === Dialog.UpperDirId) {
|
||||
this.path = path.dirname(this._path!);
|
||||
}
|
||||
|
||||
if (fv.startsWith("/")) {
|
||||
fs.stat(fv, (err, stats) => {
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (stats.isDirectory()) {
|
||||
this.path = fv;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (element.isDirectory) {
|
||||
this.path = element.fullPath;
|
||||
} else {
|
||||
// Open
|
||||
this.selectEmitter.emit(element.fullPath);
|
||||
}
|
||||
});
|
||||
fileAreaNode.appendChild(this.entryList.getHTMLElement());
|
||||
this.root.appendChild(fileAreaNode);
|
||||
|
||||
const buttonsNode = document.createElement("div");
|
||||
buttonsNode.className = "buttons";
|
||||
const cancelBtn = document.createElement("button");
|
||||
cancelBtn.innerText = "Cancel";
|
||||
cancelBtn.addEventListener("click", () => {
|
||||
this.errorEmitter.emit(new Error("Cancelled"));
|
||||
});
|
||||
buttonsNode.appendChild(cancelBtn);
|
||||
const confirmBtn = document.createElement("button");
|
||||
confirmBtn.innerText = "Confirm";
|
||||
confirmBtn.addEventListener("click", () => {
|
||||
if (this._path) {
|
||||
this.selectEmitter.emit(this._path);
|
||||
}
|
||||
});
|
||||
buttonsNode.appendChild(confirmBtn);
|
||||
this.root.appendChild(buttonsNode);
|
||||
this.entryList.layout();
|
||||
|
||||
this.path = options.defaultPath || "/";
|
||||
}
|
||||
|
||||
public get onSelect(): Event<string> {
|
||||
return this.selectEmitter.event;
|
||||
}
|
||||
|
||||
public get onError(): Event<Error> {
|
||||
return this.errorEmitter.event;
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.selectEmitter.dispose();
|
||||
this.errorEmitter.dispose();
|
||||
this.entryList.dispose();
|
||||
this.background.remove();
|
||||
}
|
||||
|
||||
private buildPath(): void {
|
||||
while (this.pathNode.lastChild) {
|
||||
this.pathNode.removeChild(this.pathNode.lastChild);
|
||||
}
|
||||
|
||||
if (!this._path) {
|
||||
throw new Error("cannot build path node without valid path");
|
||||
}
|
||||
|
||||
const pathParts = ["", ...this._path.split("/").filter((p) => p.length > 0)];
|
||||
|
||||
for (let i = 0; i < pathParts.length; i++) {
|
||||
const pathPartNode = document.createElement("div");
|
||||
pathPartNode.classList.add("path-part");
|
||||
pathPartNode.innerText = pathParts[i].length > 0 ? pathParts[i] : "/";
|
||||
|
||||
if (i === pathParts.length - 1) {
|
||||
pathPartNode.classList.add("active");
|
||||
}
|
||||
|
||||
pathPartNode.addEventListener("click", () => {
|
||||
this.path = "/" + pathParts.slice(0, i + 1).join("/");
|
||||
});
|
||||
|
||||
this.pathNode.appendChild(pathPartNode);
|
||||
}
|
||||
}
|
||||
|
||||
private set path(directory: string) {
|
||||
const ts = Date.now();
|
||||
this.list(directory).then((value) => {
|
||||
this._path = directory;
|
||||
this.buildPath();
|
||||
|
||||
while (this.filesNode.lastChild) {
|
||||
this.filesNode.removeChild(this.filesNode.lastChild);
|
||||
}
|
||||
|
||||
const items = value.filter((v) => {
|
||||
if (v.name.startsWith(".")) {
|
||||
const props = (this.options as OpenDialogOptions).properties;
|
||||
if (props && props.showHiddenFiles) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
this.entryList.setChildren(null, items.map((i: DialogEntry): ITreeElement<DialogEntry> => ({ element: i })));
|
||||
this.entryList.domFocus();
|
||||
this.entryList.setFocus([null]);
|
||||
// Clears the input on refresh
|
||||
// tslint:disable-next-line:no-any
|
||||
(<any>this.entryList).typeFilterController.onInput("");
|
||||
}).catch((ex) => {
|
||||
this.errorEmitter.emit(ex);
|
||||
});
|
||||
}
|
||||
|
||||
private get filterValue(): string {
|
||||
// tslint:disable-next-line:no-any
|
||||
return (<any>this.entryList).typeFilterController.filter._pattern;
|
||||
}
|
||||
|
||||
private async list(directory: string): Promise<ReadonlyArray<DialogEntry>> {
|
||||
return ideClient.evaluate((directory) => {
|
||||
const fs = __non_webpack_require__("fs") as typeof import("fs");
|
||||
const util = __non_webpack_require__("util") as typeof import("util");
|
||||
const path = __non_webpack_require__("path") as typeof import("path");
|
||||
|
||||
return util.promisify(fs.readdir)(directory).then((paths) => {
|
||||
paths = paths.sort();
|
||||
|
||||
return Promise.all(paths.map(p => util.promisify(fs.stat)(path.join(directory, p)))).then((stats) => {
|
||||
return {
|
||||
paths,
|
||||
stats,
|
||||
};
|
||||
});
|
||||
}).then(({ paths, stats }) => {
|
||||
return stats.map((stat, index): DialogEntry => {
|
||||
return {
|
||||
fullPath: path.join(directory, paths[index]),
|
||||
name: paths[index],
|
||||
isDirectory: stat.isDirectory(),
|
||||
lastModified: stat.mtime.toDateString(),
|
||||
size: stat.size,
|
||||
};
|
||||
});
|
||||
});
|
||||
}, directory);
|
||||
}
|
||||
}
|
||||
|
||||
interface DialogEntryData {
|
||||
icon: HTMLElement;
|
||||
size: HTMLElement;
|
||||
lastModified: HTMLElement;
|
||||
label: HighlightedLabel;
|
||||
}
|
||||
|
||||
class DialogEntryRenderer implements ITreeRenderer<DialogEntry, string, DialogEntryData> {
|
||||
public get templateId(): string {
|
||||
return "dialog-entry";
|
||||
}
|
||||
|
||||
public renderTemplate(container: HTMLElement): DialogEntryData {
|
||||
addClass(container, "dialog-entry");
|
||||
addClass(container, "dialog-grid");
|
||||
|
||||
const wrapper = append(container, $(".dialog-entry-info"));
|
||||
const icon: HTMLElement = append(wrapper, $("div"));
|
||||
const name = append(wrapper, $(".dialog-entry-name"));
|
||||
const label = new HighlightedLabel(name, false);
|
||||
append(container, wrapper);
|
||||
const size = append(container, $(".dialog-entry-size"));
|
||||
const mtime = append(container, $(".dialog-entry-mtime"));
|
||||
|
||||
return {
|
||||
icon,
|
||||
size,
|
||||
lastModified: mtime,
|
||||
label,
|
||||
};
|
||||
}
|
||||
|
||||
public renderElement(node: ITreeNode<DialogEntry, string>, index: number, templateData: DialogEntryData): void {
|
||||
templateData.icon.className = "dialog-entry-icon monaco-icon-label";
|
||||
const classes = getIconClasses(
|
||||
client.serviceCollection.get<IModelService>(IModelService) as IModelService,
|
||||
client.serviceCollection.get<IModeService>(IModeService) as IModeService,
|
||||
URI.file(node.element.name),
|
||||
node.element.isDirectory ? FileKind.FOLDER : FileKind.FILE,
|
||||
);
|
||||
templateData.icon.hidden = classes.length === 0;
|
||||
classes.forEach((c) => {
|
||||
try {
|
||||
templateData.icon.classList.add(c);
|
||||
} catch (ex) {
|
||||
// Nothin needed. Sometimes bad classes are given
|
||||
}
|
||||
});
|
||||
templateData.label.set(node.element.name, typeof node.filterData === "string" && node.element.name.toLowerCase().startsWith(node.filterData.toLowerCase()) ? [{
|
||||
start: 0,
|
||||
end: node.filterData.length,
|
||||
}] : []);
|
||||
templateData.size.innerText = node.element.size.toString();
|
||||
templateData.lastModified.innerText = node.element.lastModified;
|
||||
}
|
||||
|
||||
public disposeTemplate(templateData: DialogEntryData): void {
|
||||
// throw new Error("Method not implemented.");
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { logger } from "@coder/logger";
|
||||
import { IDisposable } from "vs/base/common/lifecycle";
|
||||
import * as actions from "vs/platform/actions/common/actions";
|
||||
import { ToggleDevToolsAction } from "vs/workbench/electron-browser/actions";
|
||||
import { ToggleDevToolsAction } from "vs/workbench/electron-browser/actions/developerActions";
|
||||
|
||||
// Intercept appending menu items so we can skip items that won't work.
|
||||
const originalAppend = actions.MenuRegistry.appendMenuItem.bind(actions.MenuRegistry);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { readFile, writeFile } from "fs";
|
||||
import { readFile, writeFile, mkdir } from "fs";
|
||||
import * as path from "path";
|
||||
import { promisify } from "util";
|
||||
import { IDisposable } from "@coder/disposable";
|
||||
@ -7,6 +7,8 @@ import * as workspaceStorage from "vs/base/node/storage";
|
||||
import * as globalStorage from "vs/platform/storage/node/storageIpc";
|
||||
import * as paths from "./paths";
|
||||
import { logger, field } from "@coder/logger";
|
||||
import { client } from "@coder/vscode/src/client";
|
||||
import { IStorageService, WillSaveStateReason } from "vs/platform/storage/common/storage";
|
||||
|
||||
class StorageDatabase implements workspaceStorage.IStorageDatabase {
|
||||
public readonly onDidChangeItemsExternal = Event.None;
|
||||
@ -20,11 +22,9 @@ class StorageDatabase implements workspaceStorage.IStorageDatabase {
|
||||
if (!navigator.sendBeacon) {
|
||||
throw new Error("cannot save state");
|
||||
}
|
||||
// TODO: Need to use navigator.sendBeacon instead of the web socket, or we
|
||||
// need to save when there is a change. Should we save as a sqlite3
|
||||
// database instead of JSON? Could send to the server the way the global
|
||||
// storage works. Or maybe fill `vscode-sqlite3` to do that.
|
||||
this.save();
|
||||
|
||||
this.triggerFlush(WillSaveStateReason.SHUTDOWN);
|
||||
navigator.sendBeacon(`/resource${this.path}`, this.content);
|
||||
});
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ class StorageDatabase implements workspaceStorage.IStorageDatabase {
|
||||
request.delete.forEach(key => this.items.delete(key));
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
return this.save();
|
||||
}
|
||||
|
||||
public close(): Promise<void> {
|
||||
@ -69,13 +69,38 @@ class StorageDatabase implements workspaceStorage.IStorageDatabase {
|
||||
return Promise.resolve("ok");
|
||||
}
|
||||
|
||||
private save(): Promise<void> {
|
||||
private async save(): Promise<void> {
|
||||
try {
|
||||
await promisify(mkdir)(path.dirname(this.path));
|
||||
} catch (ex) {}
|
||||
|
||||
return promisify(writeFile)(this.path, this.content);
|
||||
}
|
||||
|
||||
private triggerFlush(reason: WillSaveStateReason = WillSaveStateReason.NONE): boolean {
|
||||
// tslint:disable-next-line:no-any
|
||||
const storageService = client.serviceCollection.get<IStorageService>(IStorageService) as any;
|
||||
if (reason === WillSaveStateReason.SHUTDOWN && storageService.close) {
|
||||
storageService.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
if (storageService._onWillSaveState) {
|
||||
storageService._onWillSaveState.fire({ reason });
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private get content(): string {
|
||||
const json: { [key: string]: string } = {};
|
||||
this.items.forEach((value, key) => {
|
||||
json[key] = value;
|
||||
});
|
||||
|
||||
return promisify(writeFile)(this.path, JSON.stringify(json));
|
||||
return JSON.stringify(json);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,14 @@
|
||||
import * as electron from "electron";
|
||||
import { Emitter } from "@coder/events";
|
||||
import * as windowsIpc from "vs/platform/windows/node/windowsIpc";
|
||||
import { IWindowsService, INativeOpenDialogOptions, MessageBoxOptions, SaveDialogOptions, OpenDialogOptions, IMessageBoxResult, IDevToolsOptions, IEnterWorkspaceResult, CrashReporterStartOptions, INewWindowOptions } from "vs/platform/windows/common/windows";
|
||||
import { IWindowsService, INativeOpenDialogOptions, MessageBoxOptions, SaveDialogOptions, OpenDialogOptions, IMessageBoxResult, IDevToolsOptions, IEnterWorkspaceResult, CrashReporterStartOptions, INewWindowOptions, IOpenFileRequest, IAddFoldersRequest } from "vs/platform/windows/common/windows";
|
||||
import { ParsedArgs } from "vs/platform/environment/common/environment";
|
||||
import { IWorkspaceIdentifier, IWorkspaceFolderCreationData, ISingleFolderWorkspaceIdentifier } from "vs/platform/workspaces/common/workspaces";
|
||||
import { URI } from "vs/base/common/uri";
|
||||
import { IRecentlyOpened } from "vs/platform/history/common/history";
|
||||
import { ISerializableCommandAction } from "vs/platform/actions/common/actions";
|
||||
import { client } from "../client";
|
||||
import { showOpenDialog } from "../dialog";
|
||||
|
||||
/**
|
||||
* Instead of going to the shared process, we'll directly run these methods on
|
||||
@ -34,20 +35,70 @@ class WindowsService implements IWindowsService {
|
||||
private readonly window = new electron.BrowserWindow();
|
||||
|
||||
// Dialogs
|
||||
public pickFileFolderAndOpen(_options: INativeOpenDialogOptions): Promise<void> {
|
||||
throw new Error("not implemented");
|
||||
public async pickFileFolderAndOpen(_options: INativeOpenDialogOptions): Promise<void> {
|
||||
showOpenDialog({
|
||||
...(_options.dialogOptions || {}),
|
||||
properties: {
|
||||
openFile: true,
|
||||
openDirectory: true,
|
||||
},
|
||||
}).then((path) => {
|
||||
// tslint:disable-next-line:no-any
|
||||
(<any>electron.ipcMain).send("vscode:openFiles", {
|
||||
filesToOpen: [{
|
||||
fileUri: URI.file(path),
|
||||
}],
|
||||
} as IOpenFileRequest);
|
||||
}).catch((ex) => {
|
||||
//
|
||||
});
|
||||
}
|
||||
|
||||
public pickFileAndOpen(_options: INativeOpenDialogOptions): Promise<void> {
|
||||
throw new Error("not implemented");
|
||||
public async pickFileAndOpen(_options: INativeOpenDialogOptions): Promise<void> {
|
||||
showOpenDialog({
|
||||
...(_options.dialogOptions || {}),
|
||||
properties: {
|
||||
openFile: true,
|
||||
},
|
||||
}).then((path) => {
|
||||
// tslint:disable-next-line:no-any
|
||||
(<any>electron.ipcMain).send("vscode:openFiles", {
|
||||
filesToOpen: [{
|
||||
fileUri: URI.file(path),
|
||||
}],
|
||||
} as IOpenFileRequest);
|
||||
}).catch((ex) => {
|
||||
//
|
||||
});
|
||||
}
|
||||
|
||||
public pickFolderAndOpen(_options: INativeOpenDialogOptions): Promise<void> {
|
||||
throw new Error("not implemented");
|
||||
public async pickFolderAndOpen(_options: INativeOpenDialogOptions): Promise<void> {
|
||||
showOpenDialog({
|
||||
...(_options.dialogOptions || {}),
|
||||
properties: {
|
||||
openDirectory: true,
|
||||
},
|
||||
}).then((path) => {
|
||||
client.workspace = URI.file(path);
|
||||
}).catch((ex) => {
|
||||
//
|
||||
});
|
||||
}
|
||||
|
||||
public pickWorkspaceAndOpen(_options: INativeOpenDialogOptions): Promise<void> {
|
||||
throw new Error("not implemented");
|
||||
public async pickWorkspaceAndOpen(_options: INativeOpenDialogOptions): Promise<void> {
|
||||
showOpenDialog({
|
||||
...(_options.dialogOptions || {}),
|
||||
properties: {
|
||||
openDirectory: true,
|
||||
},
|
||||
}).then((path) => {
|
||||
// tslint:disable-next-line:no-any
|
||||
(<any>electron.ipcMain).send("vscode:addFolders", {
|
||||
foldersToAdd: [URI.file(path)],
|
||||
} as IAddFoldersRequest);
|
||||
}).catch((ex) => {
|
||||
//
|
||||
});
|
||||
}
|
||||
|
||||
public showMessageBox(windowId: number, options: MessageBoxOptions): Promise<IMessageBoxResult> {
|
||||
@ -70,10 +121,14 @@ class WindowsService implements IWindowsService {
|
||||
}
|
||||
|
||||
public showOpenDialog(windowId: number, options: OpenDialogOptions): Promise<string[]> {
|
||||
return new Promise((resolve): void => {
|
||||
electron.dialog.showOpenDialog(this.getWindowById(windowId), options, (filePaths, _bookmarks) => {
|
||||
resolve(filePaths);
|
||||
});
|
||||
return showOpenDialog({
|
||||
...(options || {}),
|
||||
properties: {
|
||||
openDirectory: true,
|
||||
openFile: true,
|
||||
},
|
||||
}).then((path) => {
|
||||
return [path];
|
||||
});
|
||||
}
|
||||
|
||||
@ -93,8 +148,17 @@ class WindowsService implements IWindowsService {
|
||||
throw new Error("not implemented");
|
||||
}
|
||||
|
||||
public enterWorkspace(_windowId: number, _path: string): Promise<IEnterWorkspaceResult> {
|
||||
throw new Error("not implemented");
|
||||
public enterWorkspace(_windowId: number, _path: URI): Promise<IEnterWorkspaceResult> {
|
||||
if (_path.path.endsWith(".json")) {
|
||||
client.workspace = {
|
||||
id: "Untitled",
|
||||
configPath: _path.path,
|
||||
};
|
||||
} else {
|
||||
client.workspace = _path;
|
||||
}
|
||||
|
||||
return undefined!;
|
||||
}
|
||||
|
||||
public createAndEnterWorkspace(_windowId: number, _folders?: IWorkspaceFolderCreationData[], _path?: string): Promise<IEnterWorkspaceResult> {
|
||||
@ -251,8 +315,8 @@ class WindowsService implements IWindowsService {
|
||||
return Promise.resolve(1);
|
||||
}
|
||||
|
||||
public openExternal(_url: string): Promise<boolean> {
|
||||
throw new Error("not implemented");
|
||||
public async openExternal(_url: string): Promise<boolean> {
|
||||
return typeof window.open(_url, "_blank") !== "undefined";
|
||||
}
|
||||
|
||||
public startCrashReporter(_config: CrashReporterStartOptions): Promise<void> {
|
||||
|
@ -4,7 +4,7 @@ import { Registry } from "vs/platform/registry/common/platform";
|
||||
import { IWorkbenchActionRegistry, Extensions } from "vs/workbench/common/actions";
|
||||
import { SyncActionDescriptor } from "vs/platform/actions/common/actions";
|
||||
import { ContextKeyExpr } from "vs/platform/contextkey/common/contextkey";
|
||||
import { ToggleDevToolsAction } from "vs/workbench/electron-browser/actions";
|
||||
import { ToggleDevToolsAction } from "vs/workbench/electron-browser/actions/developerActions";
|
||||
import { TerminalPasteAction } from "vs/workbench/parts/terminal/electron-browser/terminalActions";
|
||||
import { KEYBINDING_CONTEXT_TERMINAL_FOCUS } from "vs/workbench/parts/terminal/common/terminal";
|
||||
import { KeyCode, KeyMod } from "vs/base/common/keyCodes";
|
||||
|
40
packages/vscode/src/fill/workspacesService.ts
Normal file
40
packages/vscode/src/fill/workspacesService.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { URI } from "vs/base/common/uri";
|
||||
import { IEnvironmentService } from "vs/platform/environment/common/environment";
|
||||
import { ILogService } from "vs/platform/log/common/log";
|
||||
import { IWorkspaceFolderCreationData, IWorkspaceIdentifier, IWorkspacesService } from "vs/platform/workspaces/common/workspaces";
|
||||
import { WorkspacesMainService } from "vs/platform/workspaces/electron-main/workspacesMainService";
|
||||
import * as workspacesIpc from "vs/platform/workspaces/node/workspacesIpc";
|
||||
import { client } from "../client";
|
||||
|
||||
/**
|
||||
* Instead of going to the shared process, we'll directly run these methods on
|
||||
* the client. This setup means we can only control the current window.
|
||||
*/
|
||||
class WorkspacesService implements IWorkspacesService {
|
||||
// tslint:disable-next-line:no-any
|
||||
public _serviceBrand: any;
|
||||
|
||||
public createUntitledWorkspace(folders?: IWorkspaceFolderCreationData[] | undefined): Promise<IWorkspaceIdentifier> {
|
||||
const mainService = new WorkspacesMainService(
|
||||
client.serviceCollection.get<IEnvironmentService>(IEnvironmentService) as IEnvironmentService,
|
||||
client.serviceCollection.get<ILogService>(ILogService) as ILogService,
|
||||
);
|
||||
|
||||
// lib/vscode/src/vs/platform/workspaces/node/workspacesIpc.ts
|
||||
const rawFolders: IWorkspaceFolderCreationData[] = folders!;
|
||||
if (Array.isArray(rawFolders)) {
|
||||
folders = rawFolders.map(rawFolder => {
|
||||
return {
|
||||
uri: URI.revive(rawFolder.uri), // convert raw URI back to real URI
|
||||
name: rawFolder.name!,
|
||||
} as IWorkspaceFolderCreationData;
|
||||
});
|
||||
}
|
||||
|
||||
return mainService.createUntitledWorkspace(folders);
|
||||
}
|
||||
}
|
||||
|
||||
const target = workspacesIpc as typeof workspacesIpc;
|
||||
// @ts-ignore TODO: don't ignore it.
|
||||
target.WorkspacesChannelClient = WorkspacesService;
|
@ -5,144 +5,176 @@
|
||||
|
||||
import "vs/loader";
|
||||
|
||||
// Base
|
||||
import "vs/base/common/strings";
|
||||
import "vs/base/common/errors";
|
||||
//#region --- workbench/editor core
|
||||
|
||||
// Configuration
|
||||
import "vs/workbench/services/configuration/common/configurationExtensionPoint";
|
||||
|
||||
// Editor
|
||||
import "vs/editor/editor.all";
|
||||
|
||||
// Platform
|
||||
import "vs/platform/widget/browser/contextScopedHistoryWidget";
|
||||
import "vs/platform/label/electron-browser/label.contribution";
|
||||
import "vs/workbench/api/electron-browser/extensionHost.contribution";
|
||||
|
||||
// Menus/Actions
|
||||
import "vs/workbench/services/actions/electron-browser/menusExtensionPoint";
|
||||
import "vs/workbench/electron-browser/shell.contribution";
|
||||
import "vs/workbench/browser/workbench.contribution";
|
||||
|
||||
// Views
|
||||
import "vs/workbench/api/browser/viewsContainersExtensionPoint";
|
||||
import { startup } from "vs/workbench/electron-browser/main";
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region --- workbench actions
|
||||
|
||||
import "vs/workbench/browser/actions/layoutActions";
|
||||
import "vs/workbench/browser/actions/listCommands";
|
||||
import "vs/workbench/browser/actions/navigationActions";
|
||||
import "vs/workbench/browser/parts/quickopen/quickOpenActions";
|
||||
import "vs/workbench/browser/parts/quickinput/quickInputActions";
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region --- API Extension Points
|
||||
|
||||
import "vs/workbench/api/common/menusExtensionPoint";
|
||||
import "vs/workbench/api/common/configurationExtensionPoint";
|
||||
import "vs/workbench/api/browser/viewsExtensionPoint";
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region --- workbench services
|
||||
|
||||
import "vs/workbench/services/bulkEdit/electron-browser/bulkEditService";
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region --- workbench parts
|
||||
|
||||
// Localizations
|
||||
import "vs/workbench/parts/localizations/electron-browser/localizations.contribution";
|
||||
|
||||
// Workbench
|
||||
import "vs/workbench/browser/actions/toggleActivityBarVisibility";
|
||||
import "vs/workbench/browser/actions/toggleStatusbarVisibility";
|
||||
import "vs/workbench/browser/actions/toggleSidebarVisibility";
|
||||
import "vs/workbench/browser/actions/toggleSidebarPosition";
|
||||
import "vs/workbench/browser/actions/toggleEditorLayout";
|
||||
import "vs/workbench/browser/actions/toggleZenMode";
|
||||
import "vs/workbench/browser/actions/toggleCenteredLayout";
|
||||
import "vs/workbench/browser/actions/toggleTabsVisibility";
|
||||
// Preferences
|
||||
import "vs/workbench/parts/preferences/electron-browser/preferences.contribution";
|
||||
import "vs/workbench/parts/preferences/browser/keybindingsEditorContribution";
|
||||
|
||||
// Logs
|
||||
import "vs/workbench/parts/logs/electron-browser/logs.contribution";
|
||||
|
||||
import "vs/workbench/browser/parts/quickopen/quickopen.contribution";
|
||||
// Quick Open Handlers
|
||||
import "vs/workbench/parts/quickopen/browser/quickopen.contribution";
|
||||
import "vs/workbench/browser/parts/editor/editorPicker";
|
||||
import "vs/workbench/browser/parts/quickinput/quickInput.contribution";
|
||||
|
||||
// Explorer
|
||||
import "vs/workbench/parts/files/electron-browser/explorerViewlet";
|
||||
import "vs/workbench/parts/files/electron-browser/fileActions.contribution";
|
||||
import "vs/workbench/parts/files/electron-browser/files.contribution";
|
||||
|
||||
// Backup
|
||||
import "vs/workbench/parts/backup/common/backup.contribution";
|
||||
|
||||
// Stats
|
||||
import "vs/workbench/parts/stats/node/stats.contribution";
|
||||
|
||||
// Rapid Render Splash
|
||||
import "vs/workbench/parts/splash/electron-browser/partsSplash.contribution";
|
||||
|
||||
// Search
|
||||
import "vs/workbench/parts/search/electron-browser/search.contribution";
|
||||
import "vs/workbench/parts/search/browser/searchView";
|
||||
import "vs/workbench/parts/search/browser/openAnythingHandler";
|
||||
|
||||
// SCM
|
||||
import "vs/workbench/parts/scm/electron-browser/scm.contribution";
|
||||
import "vs/workbench/parts/scm/electron-browser/scmViewlet";
|
||||
|
||||
// Debug
|
||||
import "vs/workbench/parts/debug/electron-browser/debug.contribution";
|
||||
// import "vs/workbench/parts/debug/browser/debugQuickOpen";
|
||||
// import "vs/workbench/parts/debug/electron-browser/repl";
|
||||
// import "vs/workbench/parts/debug/browser/debugViewlet";
|
||||
import "vs/workbench/parts/debug/browser/debugQuickOpen";
|
||||
import "vs/workbench/parts/debug/electron-browser/repl";
|
||||
import "vs/workbench/parts/debug/browser/debugViewlet";
|
||||
|
||||
// Markers
|
||||
import "vs/workbench/parts/markers/electron-browser/markers.contribution";
|
||||
|
||||
// Comments
|
||||
import "vs/workbench/parts/comments/electron-browser/comments.contribution";
|
||||
|
||||
// HTML Preview
|
||||
import "vs/workbench/parts/html/electron-browser/html.contribution";
|
||||
|
||||
// URL Support
|
||||
import "vs/workbench/parts/url/electron-browser/url.contribution";
|
||||
|
||||
// Webview
|
||||
import "vs/workbench/parts/webview/electron-browser/webview.contribution";
|
||||
|
||||
import "vs/workbench/parts/welcome/walkThrough/electron-browser/walkThrough.contribution";
|
||||
|
||||
// Extensions Management
|
||||
import "vs/workbench/parts/extensions/electron-browser/extensions.contribution";
|
||||
import "vs/workbench/parts/extensions/browser/extensionsQuickOpen";
|
||||
import "vs/workbench/parts/extensions/electron-browser/extensionsViewlet";
|
||||
|
||||
import "vs/workbench/parts/welcome/page/electron-browser/welcomePage.contribution";
|
||||
|
||||
// Output Panel
|
||||
import "vs/workbench/parts/output/electron-browser/output.contribution";
|
||||
import "vs/workbench/parts/output/browser/outputPanel";
|
||||
|
||||
// Terminal
|
||||
import "vs/workbench/parts/terminal/electron-browser/terminal.contribution";
|
||||
import "vs/workbench/parts/terminal/browser/terminalQuickOpen";
|
||||
import "vs/workbench/parts/terminal/electron-browser/terminalPanel";
|
||||
|
||||
import "vs/workbench/electron-browser/workbench";
|
||||
|
||||
// import "vs/workbench/parts/relauncher/electron-browser/relauncher.contribution";
|
||||
// Relauncher
|
||||
import "vs/workbench/parts/relauncher/electron-browser/relauncher.contribution";
|
||||
|
||||
// Tasks
|
||||
import "vs/workbench/parts/tasks/electron-browser/task.contribution";
|
||||
|
||||
// Emmet
|
||||
import "vs/workbench/parts/emmet/browser/emmet.browser.contribution";
|
||||
import "vs/workbench/parts/emmet/electron-browser/emmet.contribution";
|
||||
|
||||
import "vs/workbench/parts/codeEditor/codeEditor.contribution";
|
||||
// CodeEditor Contributions
|
||||
import "vs/workbench/parts/codeEditor/electron-browser/codeEditor.contribution";
|
||||
|
||||
// Execution
|
||||
import "vs/workbench/parts/execution/electron-browser/execution.contribution";
|
||||
|
||||
// Snippets
|
||||
import "vs/workbench/parts/snippets/electron-browser/snippets.contribution";
|
||||
import "vs/workbench/parts/snippets/electron-browser/snippetsService";
|
||||
import "vs/workbench/parts/snippets/electron-browser/insertSnippet";
|
||||
import "vs/workbench/parts/snippets/electron-browser/configureSnippets";
|
||||
import "vs/workbench/parts/snippets/electron-browser/tabCompletion";
|
||||
|
||||
import "vs/workbench/parts/themes/electron-browser/themes.contribution";
|
||||
|
||||
// import "vs/workbench/parts/feedback/electron-browser/feedback.contribution";
|
||||
|
||||
import "vs/workbench/parts/welcome/gettingStarted/electron-browser/gettingStarted.contribution";
|
||||
// Send a Smile
|
||||
import "vs/workbench/parts/feedback/electron-browser/feedback.contribution";
|
||||
|
||||
// Update
|
||||
import "vs/workbench/parts/update/electron-browser/update.contribution";
|
||||
|
||||
// import "vs/workbench/parts/surveys/electron-browser/nps.contribution";
|
||||
// import "vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution";
|
||||
// Surveys
|
||||
import "vs/workbench/parts/surveys/electron-browser/nps.contribution";
|
||||
import "vs/workbench/parts/surveys/electron-browser/languageSurveys.contribution";
|
||||
|
||||
// Performance
|
||||
import "vs/workbench/parts/performance/electron-browser/performance.contribution";
|
||||
|
||||
// import "vs/workbench/parts/cli/electron-browser/cli.contribution";
|
||||
// CLI
|
||||
import "vs/workbench/parts/cli/electron-browser/cli.contribution";
|
||||
|
||||
import "vs/workbench/api/electron-browser/extensionHost.contribution";
|
||||
|
||||
import "vs/workbench/electron-browser/main.contribution";
|
||||
import { startup } from "vs/workbench/electron-browser/main";
|
||||
|
||||
// import "vs/workbench/parts/themes/test/electron-browser/themes.test.contribution";
|
||||
// Themes Support
|
||||
import "vs/workbench/parts/themes/electron-browser/themes.contribution";
|
||||
import "vs/workbench/parts/themes/test/electron-browser/themes.test.contribution";
|
||||
|
||||
// Watermark
|
||||
import "vs/workbench/parts/watermark/electron-browser/watermark";
|
||||
|
||||
// Welcome
|
||||
import "vs/workbench/parts/welcome/walkThrough/electron-browser/walkThrough.contribution";
|
||||
import "vs/workbench/parts/welcome/gettingStarted/electron-browser/gettingStarted.contribution";
|
||||
import "vs/workbench/parts/welcome/overlay/browser/welcomeOverlay";
|
||||
import "vs/workbench/parts/welcome/page/electron-browser/welcomePage.contribution";
|
||||
|
||||
// Outline
|
||||
import "vs/workbench/parts/outline/electron-browser/outline.contribution";
|
||||
|
||||
import "vs/workbench/services/bulkEdit/electron-browser/bulkEditService";
|
||||
|
||||
// Experiments
|
||||
import "vs/workbench/parts/experiments/electron-browser/experiments.contribution";
|
||||
|
||||
//#endregion
|
||||
|
||||
import { URI } from "vs/base/common/uri";
|
||||
|
||||
export {
|
||||
|
Reference in New Issue
Block a user