Uploader online (#26)
This commit is contained in:
@ -6,17 +6,125 @@ import "./fill/environmentService";
|
||||
import "./fill/vscodeTextmate";
|
||||
import "./fill/dom";
|
||||
import "./vscode.scss";
|
||||
|
||||
import { Client as IDEClient, IURI, IURIFactory } from "@coder/ide";
|
||||
|
||||
import { Client as IDEClient, IURI, IURIFactory, IProgress, INotificationHandle } from "@coder/ide";
|
||||
import { registerContextMenuListener } from "vs/base/parts/contextmenu/electron-main/contextmenu";
|
||||
import { LogLevel } from "vs/platform/log/common/log";
|
||||
// import { RawContextKey, IContextKeyService } from "vs/platform/contextkey/common/contextkey";
|
||||
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 { 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";
|
||||
|
||||
export class Client extends IDEClient {
|
||||
|
||||
private readonly windowId = parseInt(new Date().toISOString().replace(/[-:.TZ]/g, ""), 10);
|
||||
private _serviceCollection: ServiceCollection | undefined;
|
||||
|
||||
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);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
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),
|
||||
};
|
||||
}
|
||||
|
||||
protected initialize(): Promise<void> {
|
||||
registerContextMenuListener();
|
||||
@ -46,33 +154,6 @@ export class Client extends IDEClient {
|
||||
folderUri: URI.file(data.workingDirectory),
|
||||
});
|
||||
|
||||
// TODO: Set notification service for retrying.
|
||||
// this.retry.setNotificationService({
|
||||
// prompt: (severity, message, buttons, onCancel) => {
|
||||
// const handle = getNotificationService().prompt(severity, message, buttons, onCancel);
|
||||
// return {
|
||||
// close: () => handle.close(),
|
||||
// updateMessage: (message) => handle.updateMessage(message),
|
||||
// updateButtons: (buttons) => handle.updateActions({
|
||||
// primary: buttons.map((button) => ({
|
||||
// id: undefined,
|
||||
// label: button.label,
|
||||
// tooltip: undefined,
|
||||
// class: undefined,
|
||||
// enabled: true,
|
||||
// checked: false,
|
||||
// radio: false,
|
||||
// dispose: () => undefined,
|
||||
// run: () => {
|
||||
// button.run();
|
||||
// return Promise.resolve();
|
||||
// },
|
||||
// })),
|
||||
// }),
|
||||
// };
|
||||
// }
|
||||
// });
|
||||
|
||||
// TODO: Set up clipboard context.
|
||||
// const workbench = workbenchShell.workbench;
|
||||
// const contextKeys = workbench.workbenchParams.serviceCollection.get(IContextKeyService) as IContextKeyService;
|
||||
@ -85,16 +166,6 @@ export class Client extends IDEClient {
|
||||
}, this.initData, pathSets);
|
||||
}
|
||||
|
||||
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),
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const client = new Client();
|
||||
|
@ -59,7 +59,7 @@ const decodeStream = (encoding: string): NodeJS.ReadWriteStream => {
|
||||
return new IconvLiteDecoderStream({ encoding });
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
iconv.decodeStream = decodeStream;
|
||||
const target = iconv as typeof iconv;
|
||||
target.decodeStream = decodeStream;
|
||||
|
||||
export = iconv;
|
||||
export = target;
|
||||
|
@ -1,3 +1,7 @@
|
||||
// TODO: ?
|
||||
import { join } from "path";
|
||||
|
||||
// tslint:disable-next-line no-any
|
||||
(global as any).requireToUrl = (path: string): string => `${location.protocol}//{location.host}/${path}`;
|
||||
(global as any).requireToUrl = (path: string): string => {
|
||||
// TODO: can start with vs/...
|
||||
return join(`${location.protocol}//${location.host}/resource`, path);
|
||||
};
|
||||
|
@ -8,7 +8,7 @@ import * as globalStorage from "vs/platform/storage/node/storageIpc";
|
||||
import * as paths from "./paths";
|
||||
import { logger, field } from "@coder/logger";
|
||||
|
||||
export class StorageDatabase implements workspaceStorage.IStorageDatabase {
|
||||
class StorageDatabase implements workspaceStorage.IStorageDatabase {
|
||||
|
||||
public readonly onDidChangeItemsExternal = Event.None;
|
||||
private items = new Map<string, string>();
|
||||
@ -81,7 +81,7 @@ export class StorageDatabase implements workspaceStorage.IStorageDatabase {
|
||||
|
||||
}
|
||||
|
||||
export class GlobalStorageDatabase extends StorageDatabase implements IDisposable {
|
||||
class GlobalStorageDatabase extends StorageDatabase implements IDisposable {
|
||||
|
||||
public constructor() {
|
||||
super(path.join(paths.getAppDataPath(), "globalStorage", "state.vscdb"));
|
||||
@ -93,7 +93,10 @@ export class GlobalStorageDatabase extends StorageDatabase implements IDisposabl
|
||||
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
workspaceStorage.SQLiteStorageDatabase = StorageDatabase;
|
||||
// @ts-ignore
|
||||
globalStorage.GlobalStorageDatabaseChannelClient = GlobalStorageDatabase;
|
||||
const workspaceTarget = workspaceStorage as typeof workspaceStorage;
|
||||
// @ts-ignore TODO: don't ignore it.
|
||||
workspaceTarget.SQLiteStorageDatabase = StorageDatabase;
|
||||
|
||||
const globalTarget = globalStorage as typeof globalStorage;
|
||||
// @ts-ignore TODO: don't ignore it.
|
||||
globalTarget.GlobalStorageDatabaseChannelClient = GlobalStorageDatabase;
|
||||
|
@ -8,28 +8,29 @@ target.Registry = class Registry extends vscodeTextmate.Registry {
|
||||
...opts,
|
||||
getOnigLib: (): Promise<vscodeTextmate.IOnigLib> => {
|
||||
return new Promise<vscodeTextmate.IOnigLib>((res, rej) => {
|
||||
const onigasm = require('onigasm');
|
||||
const wasmUrl = require('!!file-loader!onigasm/lib/onigasm.wasm');
|
||||
const onigasm = require("onigasm");
|
||||
const wasmUrl = require("!!file-loader!onigasm/lib/onigasm.wasm");
|
||||
|
||||
return fetch(wasmUrl).then(resp => resp.arrayBuffer()).then(buffer => {
|
||||
return onigasm.loadWASM(buffer);
|
||||
}).then(() => {
|
||||
res({
|
||||
createOnigScanner: function (patterns) { return new onigasm.OnigScanner(patterns); },
|
||||
createOnigString: function (s) { return new onigasm.OnigString(s); }
|
||||
})
|
||||
createOnigString: function (s) { return new onigasm.OnigString(s); },
|
||||
});
|
||||
}).catch(reason => rej(reason));
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
enum StandardTokenType {
|
||||
Other = 0,
|
||||
Comment = 1,
|
||||
String = 2,
|
||||
RegEx = 4,
|
||||
};
|
||||
Comment = 1,
|
||||
String = 2,
|
||||
RegEx = 4,
|
||||
}
|
||||
|
||||
// Any needed here to override const
|
||||
(<any>target).StandardTokenType = StandardTokenType;
|
||||
// tslint:disable-next-line no-any to override const
|
||||
(target as any).StandardTokenType = StandardTokenType;
|
||||
|
@ -281,5 +281,6 @@ class WindowsService implements IWindowsService {
|
||||
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
windowsIpc.WindowsChannelClient = WindowsService;
|
||||
const target = windowsIpc as typeof windowsIpc;
|
||||
// @ts-ignore TODO: don't ignore it.
|
||||
target.WindowsChannelClient = WindowsService;
|
||||
|
@ -1,59 +0,0 @@
|
||||
import { Upload as BaseUpload, IURI } from "@coder/ide";
|
||||
import { client } from "./entry";
|
||||
import { INotificationService, Severity } from "vs/platform/notification/common/notification";
|
||||
import { IProgressService2, ProgressLocation } from "vs/workbench/services/progress/common/progress";
|
||||
|
||||
export class Upload extends BaseUpload {
|
||||
|
||||
public constructor(
|
||||
@INotificationService notificationService: INotificationService,
|
||||
@IProgressService2 progressService: IProgressService2,
|
||||
) {
|
||||
super({
|
||||
error: (error) => {
|
||||
notificationService.error(error);
|
||||
},
|
||||
prompt: (message, choices) => {
|
||||
return new Promise((resolve) => {
|
||||
notificationService.prompt(
|
||||
Severity.Error,
|
||||
message,
|
||||
choices.map((label) => ({
|
||||
label,
|
||||
run: () => {
|
||||
resolve(label);
|
||||
},
|
||||
})),
|
||||
() => {
|
||||
resolve(undefined);
|
||||
},
|
||||
);
|
||||
});
|
||||
},
|
||||
}, {
|
||||
start: (title, task) => {
|
||||
let lastProgress = 0;
|
||||
|
||||
return progressService.withProgress({
|
||||
location: ProgressLocation.Notification,
|
||||
title,
|
||||
cancellable: true,
|
||||
}, (progress) => {
|
||||
return task({
|
||||
report: (p) => {
|
||||
progress.report({ increment: p - lastProgress });
|
||||
lastProgress = p;
|
||||
},
|
||||
});
|
||||
}, () => {
|
||||
this.cancel();
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
public async uploadDropped(event: DragEvent, uri?: IURI): Promise<string[]> {
|
||||
return super.uploadDropped(event, uri || (await client.workspace).mountUri);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user