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) { static injectScript(id, url) {
id = this.escapeID(id); id = this.escapeID(id);
return new Promise(resolve => { return new Promise((resolve, reject) => {
const script = this.getElement(`#${id}`, this.bdScripts) || this.createElement("script", {id}); const script = this.getElement(`#${id}`, this.bdScripts) || this.createElement("script", {id});
script.src = url; script.src = url;
script.onload = resolve; script.onload = resolve;
script.onerror = reject;
this.bdScripts.append(script); this.bdScripts.append(script);
}); });
} }

View File

@ -1,3 +1,4 @@
import Logger from "../../../common/logger";
import DOMManager from "./dommanager"; import DOMManager from "./dommanager";
export default new class Editor { 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 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}); DOMManager.linkStyle("monaco-style", `${baseUrl}/vs/editor/editor.main.min.css`, {documentHead: true});
await DOMManager.injectScript("monaco-script", `${baseUrl}/vs/loader.min.js`);
try {
const amdLoader = window.require; // Grab Monaco's amd loader await DOMManager.injectScript("monaco-script", `${baseUrl}/vs/loader.min.js`);
window.require = commonjsLoader; // Revert to commonjs
// this.log(amdLoader, window.require); const amdLoader = window.require; // Grab Monaco's amd loader
amdLoader.config({paths: {vs: `${baseUrl}/vs`}}); window.require = commonjsLoader; // Revert to commonjs
amdLoader(["vs/editor/editor.main"], () => {}); // exposes the monaco global
// 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 { .monaco-editor .view-overlays .current-line {
width: 1e+06px !important; 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() { componentDidMount() {
this.editor = window.monaco.editor.create(document.getElementById(this.props.id), { if (window.monaco?.editor) {
value: this.props.value, this.editor = window.monaco.editor.create(document.getElementById(this.props.id), {
language: this.props.language, value: this.props.value,
theme: DiscordModules.UserSettingsStore.theme == "light" ? "vs" : "vs-dark", language: this.props.language,
fontSize: Settings.get("settings", "editor", "fontSize"), theme: DiscordModules.UserSettingsStore.theme == "light" ? "vs" : "vs-dark",
lineNumbers: Settings.get("settings", "editor", "lineNumbers"), fontSize: Settings.get("settings", "editor", "fontSize"),
minimap: {enabled: Settings.get("settings", "editor", "minimap")}, lineNumbers: Settings.get("settings", "editor", "lineNumbers"),
hover: {enabled: Settings.get("settings", "editor", "hover")}, minimap: {enabled: Settings.get("settings", "editor", "minimap")},
quickSuggestions: { hover: {enabled: Settings.get("settings", "editor", "hover")},
other: Settings.get("settings", "editor", "quickSuggestions"), quickSuggestions: {
comments: Settings.get("settings", "editor", "quickSuggestions"), other: Settings.get("settings", "editor", "quickSuggestions"),
strings: Settings.get("settings", "editor", "quickSuggestions") comments: Settings.get("settings", "editor", "quickSuggestions"),
}, strings: Settings.get("settings", "editor", "quickSuggestions")
renderWhitespace: Settings.get("settings", "editor", "renderWhitespace") },
}); 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); if (DiscordModules.UserSettingsStore) DiscordModules.UserSettingsStore.addChangeListener(this.onThemeChange);
this.bindings.push(this.editor.onDidChangeModelContent(this.onChange)); window.addEventListener("resize", this.resize);
} }
componentWillUnmount() { componentWillUnmount() {
@ -64,7 +84,7 @@ export default class CodeEditor extends React.Component {
const newTheme = DiscordModules.UserSettingsStore.theme === "light" ? "vs" : "vs-dark"; const newTheme = DiscordModules.UserSettingsStore.theme === "light" ? "vs" : "vs-dark";
if (newTheme === this.props.theme) return; if (newTheme === this.props.theme) return;
this.props.theme = newTheme; 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();} get value() {return this.editor.getValue();}