src/components/editor/Editor.js
import React, { Component } from "react";
import AceEditor from "react-ace";
import "brace/mode/javascript";
import "brace/theme/github";
import "brace/ext/searchbox";
import "brace/ext/language_tools";
import customCompleter from "./customCompleter.js";
import KeyboardShortcut from "./KeyboardShortcut.js";
import { browserType } from "../../utils/browserType";
import FontSize from "./FontSize.js";
import copy from "copy-to-clipboard";
/**
 * Editor is a React Component that create the Ace Editor in the DOM.
 */
class Editor extends Component {
    /**
     * Called when the Edtior is unmounting (Being removed from the DOM)
     * 
     * Editor will unmount when MYR enters ViewOnly mode, and we want to render
     * whatever the code that's in the editor.
     */
    componentWillUnmount() {
        this.refreshText();
    }
    refreshText = () => {
        // Updates state in reducer before closing editor
        const text = window.ace.edit("ace-editor").getSession().getValue();
        this.props.refresh(text, this.props.user ? this.props.user.uid : "anon");
        // Forces render cycle so user sees up to date view when viewonly loads
        this.props.render(text);
    }
    /**
     * Called when the Editor is mounted (component has been rendererd to the DOM)
     * 
     * It sets custom completer of MYR API to editor, 
     * and add listener to check whether user have unsaved changes.
     */
    componentDidMount() {
        try {
            // eslint-disable-next-line
            this.refs.aceEditor.editor.completers = [customCompleter];
        } catch (error) {
            console.error("Unable to attach custom completers");
        }
        // Warn the issue before refreshing the page
        window.addEventListener("beforeunload", (event) => {
            let text;
            try {
                let editor = window.ace.edit("ace-editor");
                text = editor.getSession().getValue();
            } catch (err) {
                console.error(err);
            }
            if (this.props.savedText !== text) {
                event.preventDefault();
                event.returnValue = "You may have unsaved scene changes!";
            }
        });
        this.setState({"previousSettings":this.props.settings});
    }
    /**
     * Called when the editor is loaded.
     * It sets options to set the maximum error editor accepts and set the EMCAScript version to 6
     */
    onLoad() {
        window.ace.edit("ace-editor").session.$worker.send("setOptions", [{
            "maxerr": 1000,
            "esversion": 6
        }]);
    }
    componentDidUpdate(){
        if(JSON.stringify(this.state.previousSettings) !== JSON.stringify(this.props.settings) &&
        this.props.user) {
            this.props.userActions.updateUserSettings(this.props.user.uid,this.props.settings);
            this.setState({"previousSettings":this.props.settings});
        }
    }
    
    /**
     * Creates the editor in the DOM
     */
    render() {
        return (
            <div>
                <AceEditor
                    editorProps={{
                        $blockScrolling: Infinity,
                    }}
                    height="88vh"
                    mode="javascript"
                    name="ace-editor"
                    // eslint-disable-next-line
                    ref="aceEditor"
                    theme="github"
                    commands={[{
                        name: "copyLine",
                        bindKey: {win: "Ctrl-L", mac: "Command-L"},
                        exec: () => {let line = window.ace.edit("ace-editor").selection.getCursor().row;
                            let copyText = window.ace.edit("ace-editor").session.getTextRange({start: {row: line, column: 0}, end: {row: line + 1, column: 0}});
                            if (copyText.charAt(-1) === "\n") {
                                copyText = copyText.slice(0, -1);
                            }
                            copy(copyText);
                        }
                    }]}
                    fontSize = {this.props.settings.fontSize}
                    value={this.props.text}
                    width="100%"
                    wrapEnabled={true}
                    enableBasicAutocompletion={false}
                    enableLiveAutocompletion={true}
                    onLoad={this.onLoad}
                />
                { browserType() === "desktop" ? <div><KeyboardShortcut/> 
                    <FontSize userActions={this.props.userActions} settings={this.props.settings} refreshText={this.refreshText}/></div> : null }
            </div>
        );
    }
}
export default Editor;