Fallback when Monaco load fails (#1278)

This commit is contained in:
Qb 2022-06-25 08:09:00 +02:00 committed by GitHub
parent ac5d2baf57
commit c4a400e292
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 27 deletions

View File

@ -91,10 +91,11 @@ export default class DOMManager {
static injectScript(id, url) {
id = this.escapeID(id);
return new Promise(resolve => {
return new Promise((resolve, reject) => {
const script = this.getElement(`#${id}`, this.bdScripts) || this.createElement("script", {id});
script.src = url;
script.onload = resolve;
script.onerror = reject;
this.bdScripts.append(script);
});
}

View File

@ -1,3 +1,4 @@
import Logger from "../../../common/logger";
import DOMManager from "./dommanager";
export default new class Editor {
@ -22,12 +23,23 @@ export default new class Editor {
delete window.module; // Make monaco think this isn't a local node script or else it freaks out
DOMManager.linkStyle("monaco-style", `${baseUrl}/vs/editor/editor.main.min.css`, {documentHead: true});
await DOMManager.injectScript("monaco-script", `${baseUrl}/vs/loader.min.js`);
const amdLoader = window.require; // Grab Monaco's amd loader
window.require = commonjsLoader; // Revert to commonjs
// this.log(amdLoader, window.require);
amdLoader.config({paths: {vs: `${baseUrl}/vs`}});
amdLoader(["vs/editor/editor.main"], () => {}); // exposes the monaco global
try {
await DOMManager.injectScript("monaco-script", `${baseUrl}/vs/loader.min.js`);
const amdLoader = window.require; // Grab Monaco's amd loader
window.require = commonjsLoader; // Revert to commonjs
// Configure Monaco's AMD loader
amdLoader.config({paths: {vs: `${baseUrl}/vs`}});
amdLoader(["vs/editor/editor.main"], () => {}); // exposes the monaco global
}
catch (e) {
Logger.error("Editor", "Failed to load monaco editor", e);
}
finally {
// Revert the global require to CommonJS
window.require = commonjsLoader;
}
}
};

View File

@ -97,4 +97,12 @@
.monaco-editor .view-overlays .current-line {
width: 1e+06px !important;
}
}
.bd-fallback-editor {
height: 100%;
width: 100%;
resize: none;
overflow: auto;
white-space: nowrap;
}

View File

@ -32,25 +32,45 @@ export default class CodeEditor extends React.Component {
}
componentDidMount() {
this.editor = window.monaco.editor.create(document.getElementById(this.props.id), {
value: this.props.value,
language: this.props.language,
theme: DiscordModules.UserSettingsStore.theme == "light" ? "vs" : "vs-dark",
fontSize: Settings.get("settings", "editor", "fontSize"),
lineNumbers: Settings.get("settings", "editor", "lineNumbers"),
minimap: {enabled: Settings.get("settings", "editor", "minimap")},
hover: {enabled: Settings.get("settings", "editor", "hover")},
quickSuggestions: {
other: Settings.get("settings", "editor", "quickSuggestions"),
comments: Settings.get("settings", "editor", "quickSuggestions"),
strings: Settings.get("settings", "editor", "quickSuggestions")
},
renderWhitespace: Settings.get("settings", "editor", "renderWhitespace")
});
if (window.monaco?.editor) {
this.editor = window.monaco.editor.create(document.getElementById(this.props.id), {
value: this.props.value,
language: this.props.language,
theme: DiscordModules.UserSettingsStore.theme == "light" ? "vs" : "vs-dark",
fontSize: Settings.get("settings", "editor", "fontSize"),
lineNumbers: Settings.get("settings", "editor", "lineNumbers"),
minimap: {enabled: Settings.get("settings", "editor", "minimap")},
hover: {enabled: Settings.get("settings", "editor", "hover")},
quickSuggestions: {
other: Settings.get("settings", "editor", "quickSuggestions"),
comments: Settings.get("settings", "editor", "quickSuggestions"),
strings: Settings.get("settings", "editor", "quickSuggestions")
},
renderWhitespace: Settings.get("settings", "editor", "renderWhitespace")
});
this.bindings.push(this.editor.onDidChangeModelContent(this.onChange));
}
else {
const textarea = document.createElement("textarea");
textarea.className = "bd-fallback-editor";
textarea.value = this.props.value;
textarea.onchange = (e) => this.onChange(e.target.value);
textarea.oninput = (e) => this.onChange(e.target.value);
this.editor = {
dispose: () => textarea.remove(),
getValue: () => textarea.value,
setValue: (value) => textarea.value = value,
layout: () => {},
};
document.getElementById(this.props.id).appendChild(textarea);
}
window.addEventListener("resize", this.resize);
if (DiscordModules.UserSettingsStore) DiscordModules.UserSettingsStore.addChangeListener(this.onThemeChange);
this.bindings.push(this.editor.onDidChangeModelContent(this.onChange));
window.addEventListener("resize", this.resize);
}
componentWillUnmount() {
@ -64,7 +84,7 @@ export default class CodeEditor extends React.Component {
const newTheme = DiscordModules.UserSettingsStore.theme === "light" ? "vs" : "vs-dark";
if (newTheme === this.props.theme) return;
this.props.theme = newTheme;
window.monaco.editor.setTheme(this.props.theme);
if (window.monaco?.editor) window.monaco.editor.setTheme(this.props.theme);
}
get value() {return this.editor.getValue();}