{ - this.codemirrorContainer = element; + return () => { + if (cmRef.current) { + cmRef.current.off('keyup', handleKeyUp); + } + props.provideController(null); + }; + }, []); + + useEffect(() => { + if (cmRef.current) { + cmRef.current.on('change', handleChange); + } + return () => { + cmRef.current.off('change', handleChange); + }; + }, [props.autorefresh, props.isPlaying, props.file.id]); + + useEffect(() => { + if (cmRef.current) { + cmRef.current.on('keydown', handleKeydown); + } + return () => { + cmRef.current.off('keydown', handleKeydown); + }; + }, [props.autocompleteHinter]); + + useEffect(() => { + initializeDocuments(props.files); + }, [props.files]); + + useEffect(() => { + if (!cmRef.current) return; + + const fileMode = getFileMode(props.file.name); + if (fileMode === 'javascript') { + cmRef.current.setOption('emmet', { + preview: ['html'], + markTagPairs: false, + autoRenameTags: true + }); + } + + if (props.file.id !== prevFileId.current) { + const oldDoc = cmRef.current.swapDoc(docsRef.current[props.file.id]); + docsRef.current[prevFileId.current] = oldDoc; + cmRef.current.focus(); + + if (!props.unsavedChanges) { + setTimeout(() => props.setUnsavedChanges(false), 400); + } + + prevFileId.current = props.file.id; + cmRef.current.focus(); + } + }, [props.file.id, props.file.name, props.unsavedChanges]); + + // useEffect(() => { + // if (!cmRef.current) return; + // if (!props.unsavedChanges) { + // const timeout = setTimeout(() => { + // props.setUnsavedChanges(false); + // }, 400); + // // eslint-disable-next-line consistent-return + // return () => clearTimeout(timeout); + // } + // }, [props.unsavedChanges]); + + useEffect(() => { + if (!cmRef.current) return; + // prettier-ignore + cmRef.current.getWrapperElement().style['font-size'] = + `${props.fontSize}px`; + }, [props.fontSize]); + + useEffect(() => { + if (!cmRef.current) return; + cmRef.current.setOption('lineWrapping', props.linewrap); + }, [props.linewrap]); + + useEffect(() => { + if (!cmRef.current) return; + cmRef.current.setOption('theme', `p5-${props.theme}`); + }, [props.theme]); + + useEffect(() => { + if (!cmRef.current) return; + cmRef.current.setOption('lineNumbers', props.lineNumbers); + }, [props.lineNumbers]); + + useEffect(() => { + if (!cmRef.current) return; + cmRef.current.setOption('autoCloseBrackets', props.autocloseBracketsQuotes); + }, [props.autocloseBracketsQuotes]); + + useEffect(() => { + if (!cmRef.current) return; + + if (props.runtimeErrorWarningVisible) { + props.consoleEvents.forEach((consoleEvent) => { + if (consoleEvent.method === 'error') { + const errorObj = { stack: consoleEvent.data[0].toString() }; + StackTrace.fromError(errorObj).then((stackLines) => { + props.expandConsole(); + const line = stackLines.find( + (l) => l.fileName && l.fileName.startsWith('/') + ); + if (!line) return; + const fileNameArray = line.fileName.split('/'); + const fileName = fileNameArray.slice(-1)[0]; + const filePath = fileNameArray.slice(0, -1).join('/'); + const fileWithError = props.files.find( + (f) => f.name === fileName && f.filePath === filePath + ); + props.setSelectedFile(fileWithError.id); + cmRef.current.addLineClass( + line.lineNumber - 1, + 'background', + 'line-runtime-error' + ); + }); + } + }); + } else { + for (let i = 0; i < cmRef.current.lineCount(); i += 1) { + cmRef.current.removeLineClass(i, 'background', 'line-runtime-error'); + } + } + }, [props.runtimeErrorWarningVisible, props.consoleEvents]); + + useEffect(() => { + if (!cmRef.current) return; + for (let i = 0; i < cmRef.current.lineCount(); i += 1) { + cmRef.current.removeLineClass(i, 'background', 'line-runtime-error'); + } + }, [props.file.id]); + + const editorSectionClass = classNames({ + editor: true, + 'sidebar--contracted': !props.isExpanded + }); + + const editorHolderClass = classNames({ + 'editor-holder': true, + 'editor-holder--hidden': props.file.fileType === 'folder' || props.file.url + }); + + return ( + + {(matches) => + matches ? ( + + + { + props.collapseSidebar(); + props.closeProjectOptions(); }} - className={editorHolderClass} - /> - {this.props.file.url ? ( - + > + + + + + + + + {props.file.name} + + + + + + + {props.file.url ? ( + + ) : null} + + + ) : ( + + + + + {props.file.name} + + + + + + {props.file.url ? ( + ) : null} - ) : ( - - - - - {this.props.file.name} - - - - - { - this.codemirrorContainer = element; - }} - /> - {this.props.file.url ? ( - - ) : null} - - - - ) - } - - ); - } + + ) + } +
{ + this.codemirrorContainer = element; + }} + className={editorHolderClass} + /> + {this.props.file.url ? ( + + ) : null} + +