mirror of
https://github.com/coder/code-server.git
synced 2026-05-12 15:27:25 +02:00
Getting the client to run (#12)
* Clean up workbench and integrate initialization data * Uncomment Electron fill * Run server & client together * Clean up Electron fill & patch * Bind fs methods This makes them usable with the promise form: `promisify(access)(...)`. * Add space between tag and title to browser logger * Add typescript dep to server and default __dirname for path * Serve web files from server * Adjust some dev options * Rework workbench a bit to use a class and catch unexpected errors * No mkdirs for now, fix util fill, use bash with exec * More fills, make general client abstract * More fills * Fix cp.exec * Fix require calls in fs fill being aliased * Create data and storage dir * Implement fs.watch Using exec for now. * Implement storage database fill * Fix os export and homedir * Add comment to use navigator.sendBeacon * Fix fs callbacks (some args are optional) * Make sure data directory exists when passing it back * Update patch * Target es5 * More fills * Add APIs required for bootstrap-fork to function (#15) * Add bootstrap-fork execution * Add createConnection * Bundle bootstrap-fork into cli * Remove .node directory created from spdlog * Fix npm start * Remove unnecessary comment * Add webpack-hot-middleware if CLI env is not set * Add restarting to shared process * Fix starting with yarn
This commit is contained in:
132
packages/ide/src/fill/clipboard.ts
Normal file
132
packages/ide/src/fill/clipboard.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
import { IDisposable } from "@coder/disposable";
|
||||
import { Emitter } from "@coder/events";
|
||||
|
||||
/**
|
||||
* Native clipboard.
|
||||
*/
|
||||
export class Clipboard {
|
||||
|
||||
private readonly enableEmitter: Emitter<boolean> = new Emitter();
|
||||
private _isEnabled: boolean = false;
|
||||
|
||||
/**
|
||||
* Ask for permission to use the clipboard.
|
||||
*/
|
||||
public initialize(): void {
|
||||
// tslint:disable no-any
|
||||
const navigatorClip = (navigator as any).clipboard;
|
||||
const navigatorPerms = (navigator as any).permissions;
|
||||
// tslint:enable no-any
|
||||
if (navigatorClip && navigatorPerms) {
|
||||
navigatorPerms.query({
|
||||
name: "clipboard-read",
|
||||
}).then((permissionStatus: {
|
||||
onchange: () => void,
|
||||
state: "denied" | "granted" | "prompt",
|
||||
}) => {
|
||||
const updateStatus = (): void => {
|
||||
this._isEnabled = permissionStatus.state !== "denied";
|
||||
this.enableEmitter.emit(this.isEnabled);
|
||||
};
|
||||
updateStatus();
|
||||
permissionStatus.onchange = (): void => {
|
||||
updateStatus();
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the native clipboard is supported.
|
||||
*/
|
||||
public get isSupported(): boolean {
|
||||
// tslint:disable no-any
|
||||
return typeof navigator !== "undefined"
|
||||
&& typeof (navigator as any).clipboard !== "undefined"
|
||||
&& typeof (navigator as any).clipboard.readText !== "undefined";
|
||||
// tslint:enable no-any
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a function to be called when the native clipboard is
|
||||
* enabled/disabled.
|
||||
*/
|
||||
public onPermissionChange(cb: (enabled: boolean) => void): IDisposable {
|
||||
return this.enableEmitter.event(cb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read text from the clipboard.
|
||||
*/
|
||||
public readText(): Promise<string> {
|
||||
return this.instance ? this.instance.readText() : Promise.resolve("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Write text to the clipboard.
|
||||
*/
|
||||
public writeText(value: string): Promise<void> {
|
||||
return this.instance
|
||||
? this.instance.writeText(value)
|
||||
: this.writeTextFallback(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the clipboard is currently enabled.
|
||||
*/
|
||||
public get isEnabled(): boolean {
|
||||
return !!this._isEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return clipboard instance if there is one.
|
||||
*/
|
||||
private get instance(): ({
|
||||
readText(): Promise<string>;
|
||||
writeText(value: string): Promise<void>;
|
||||
}) | undefined {
|
||||
// tslint:disable-next-line no-any
|
||||
return this.isSupported ? (navigator as any).clipboard : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fallback for writing text to the clipboard.
|
||||
* Taken from https://hackernoon.com/copying-text-to-clipboard-with-javascript-df4d4988697f
|
||||
*/
|
||||
private writeTextFallback(value: string): Promise<void> {
|
||||
// Note the current focus and selection.
|
||||
const active = document.activeElement as HTMLElement;
|
||||
const selection = document.getSelection();
|
||||
const selected = selection && selection.rangeCount > 0
|
||||
? selection.getRangeAt(0)
|
||||
: false;
|
||||
|
||||
// Insert a hidden textarea to put the text to copy in.
|
||||
const el = document.createElement("textarea");
|
||||
el.value = value;
|
||||
el.setAttribute("readonly", "");
|
||||
el.style.position = "absolute";
|
||||
el.style.left = "-9999px";
|
||||
document.body.appendChild(el);
|
||||
|
||||
// Select the textarea and execute a copy (this will only work as part of a
|
||||
// user interaction).
|
||||
el.select();
|
||||
document.execCommand("copy");
|
||||
|
||||
// Remove the textarea and put focus and selection back to where it was
|
||||
// previously.
|
||||
document.body.removeChild(el);
|
||||
active.focus();
|
||||
if (selected && selection) {
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(selected);
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Global clipboard instance since it's used in the Electron fill.
|
||||
export const clipboard = new Clipboard();
|
||||
Reference in New Issue
Block a user