|
|
|
@ -12,7 +12,11 @@ import {
|
|
|
|
|
reaction,
|
|
|
|
|
runInAction,
|
|
|
|
|
} from "mobx";
|
|
|
|
|
import { IMonacoSetup, loadMonaco } from "../../../monaco-loader";
|
|
|
|
|
import {
|
|
|
|
|
IMonacoSetup,
|
|
|
|
|
loadMonaco,
|
|
|
|
|
waitForLoadedMonaco,
|
|
|
|
|
} from "../../../monaco-loader";
|
|
|
|
|
import { IPlaygroundProject, IPreviewState } from "../../../shared";
|
|
|
|
|
import { monacoEditorVersion } from "../../monacoEditorVersion";
|
|
|
|
|
import { Debouncer } from "../../utils/Debouncer";
|
|
|
|
@ -56,12 +60,23 @@ export class PlaygroundModel {
|
|
|
|
|
|
|
|
|
|
public readonly serializer = new StateUrlSerializer(this);
|
|
|
|
|
|
|
|
|
|
reload(): void {
|
|
|
|
|
public reload(): void {
|
|
|
|
|
this.reloadKey++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private readonly _previewHandlers = new Set<IPreviewHandler>();
|
|
|
|
|
|
|
|
|
|
private _wasEverNonFullScreen = false;
|
|
|
|
|
public get wasEverNonFullScreen() {
|
|
|
|
|
if (this._wasEverNonFullScreen) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (!this.settings.previewFullScreen) {
|
|
|
|
|
this._wasEverNonFullScreen = true;
|
|
|
|
|
}
|
|
|
|
|
return this._wasEverNonFullScreen;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@computed.struct
|
|
|
|
|
get monacoSetup(): IMonacoSetup {
|
|
|
|
|
const sourceOverride = this.serializer.sourceOverride;
|
|
|
|
@ -125,27 +140,61 @@ export class PlaygroundModel {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private readonly debouncer = new Debouncer(250);
|
|
|
|
|
private readonly debouncer = new Debouncer(700);
|
|
|
|
|
|
|
|
|
|
@observable
|
|
|
|
|
public isDirty = false;
|
|
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
|
let lastState = this.state;
|
|
|
|
|
|
|
|
|
|
this.dispose.track({
|
|
|
|
|
dispose: reaction(
|
|
|
|
|
() => ({ state: this.state }),
|
|
|
|
|
({ state }) => {
|
|
|
|
|
this.debouncer.run(() => {
|
|
|
|
|
if (!this.settings.autoReload) {
|
|
|
|
|
if (
|
|
|
|
|
JSON.stringify(state.monacoSetup) ===
|
|
|
|
|
JSON.stringify(lastState.monacoSetup) &&
|
|
|
|
|
state.key === lastState.key
|
|
|
|
|
) {
|
|
|
|
|
this.isDirty = true;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
const action = () => {
|
|
|
|
|
this.isDirty = false;
|
|
|
|
|
lastState = state;
|
|
|
|
|
for (const handler of this._previewHandlers) {
|
|
|
|
|
handler.handlePreview(state);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (state.key !== lastState.key) {
|
|
|
|
|
action(); // sync update
|
|
|
|
|
} else {
|
|
|
|
|
this.debouncer.run(action);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{ name: "update preview" }
|
|
|
|
|
),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const observablePromise = new ObservablePromise(loadMonaco());
|
|
|
|
|
const observablePromise = new ObservablePromise(waitForLoadedMonaco());
|
|
|
|
|
let disposable: Disposable | undefined = undefined;
|
|
|
|
|
|
|
|
|
|
loadMonaco().then((m) => {
|
|
|
|
|
waitForLoadedMonaco().then((m) => {
|
|
|
|
|
this.dispose.track(
|
|
|
|
|
monaco.editor.addEditorAction({
|
|
|
|
|
id: "reload",
|
|
|
|
|
label: "Reload",
|
|
|
|
|
run: (editor, ...args) => {
|
|
|
|
|
this.reload();
|
|
|
|
|
},
|
|
|
|
|
keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter],
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const options =
|
|
|
|
|
monaco.languages.typescript.javascriptDefaults.getCompilerOptions();
|
|
|
|
|
monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions(
|
|
|
|
@ -190,6 +239,28 @@ export class PlaygroundModel {
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setCodeString(codeStringName: string, value: string) {
|
|
|
|
|
function escapeRegexpChars(str: string) {
|
|
|
|
|
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, "\\$&");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const regexp = new RegExp(
|
|
|
|
|
"(\\b" +
|
|
|
|
|
escapeRegexpChars(codeStringName) +
|
|
|
|
|
":[^\\w`]*`)([^`\\\\]|\\n|\\\\\\\\|\\\\`)*`"
|
|
|
|
|
);
|
|
|
|
|
const js = this.js;
|
|
|
|
|
const str = value
|
|
|
|
|
.replaceAll("\\", "\\\\")
|
|
|
|
|
.replaceAll("$", "\\$")
|
|
|
|
|
.replaceAll("`", "\\`");
|
|
|
|
|
const newJs = js.replace(regexp, "$1" + str + "`");
|
|
|
|
|
const autoReload = this.settings.autoReload;
|
|
|
|
|
this.settings.autoReload = false;
|
|
|
|
|
this.js = newJs;
|
|
|
|
|
this.settings.autoReload = autoReload;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public showSettingsDialog(): void {
|
|
|
|
|
this.settingsDialogModel = new SettingsDialogModel(
|
|
|
|
|
this.settings.settings
|
|
|
|
|