11import PropTypes from 'prop-types' ;
22import React , { useCallback , useEffect , useRef , useState } from 'react' ;
3- import CodeMirror from 'codemirror' ;
43import { withTranslation } from 'react-i18next' ;
54import StackTrace from 'stacktrace-js' ;
65
@@ -36,7 +35,6 @@ import { FolderIcon } from '../../../../common/icons';
3635import IconButton from '../../../../common/IconButton' ;
3736
3837import { hideHinter } from './hinter' ;
39- import getFileMode from './utils' ;
4038import tidyCode from './tidier' ;
4139import useCodeMirror from './codemirror' ;
4240import { useEffectWithComparison } from '../../hooks/custom-hooks' ;
@@ -50,7 +48,6 @@ function Editor({
5048 lineNumbers,
5149 closeProjectOptions,
5250 setSelectedFile,
53- unsavedChanges,
5451 setUnsavedChanges,
5552 lintMessages,
5653 lintWarning,
@@ -75,7 +72,6 @@ function Editor({
7572} ) {
7673 const [ currentLine , setCurrentLine ] = useState ( 1 ) ;
7774 const beep = useRef ( ) ;
78- const docs = useRef ( ) ;
7975
8076 const updateLintingMessageAccessibility = debounce ( ( annotations ) => {
8177 clearLintMessage ( ) ;
@@ -89,6 +85,8 @@ function Editor({
8985 }
9086 } , 2000 ) ;
9187
88+ // The useCodeMirror hook manages CodeMirror state and returns
89+ // a reference to the actual CM instance.
9290 const {
9391 setupCodeMirrorOnContainerMounted,
9492 teardownCodeMirror,
@@ -105,6 +103,7 @@ function Editor({
105103 hideRuntimeErrorWarning,
106104 updateFileContent,
107105 file,
106+ files,
108107 autorefresh,
109108 isPlaying,
110109 clearConsole,
@@ -124,22 +123,11 @@ function Editor({
124123 getContent
125124 } ) ;
126125
127- const initializeDocuments = ( ) => {
128- docs . current = { } ;
129- files . forEach ( ( currentFile ) => {
130- if ( currentFile . name !== 'root' ) {
131- docs . current [ currentFile . id ] = CodeMirror . Doc (
132- currentFile . content ,
133- getFileMode ( currentFile . name )
134- ) ;
135- }
136- } ) ;
137- } ;
138-
139- // Component did mount
126+ // When the CM container div mounts, we set up CodeMirror.
140127 const onContainerMounted = useCallback ( setupCodeMirrorOnContainerMounted , [ ] ) ;
141128
142- // Component did mount
129+ // This is acting as a "componentDidMount" call where it runs once
130+ // at the start and never again. It also provides a cleanup function.
143131 useEffect ( ( ) => {
144132 beep . current = new Audio ( beepUrl ) ;
145133
@@ -156,43 +144,6 @@ function Editor({
156144 } ;
157145 } , [ ] ) ;
158146
159- useEffect ( ( ) => {
160- initializeDocuments ( ) ;
161- } , [ files ] ) ;
162-
163- useEffectWithComparison (
164- ( _ , prevProps ) => {
165- const fileMode = getFileMode ( file . name ) ;
166- if ( fileMode === 'javascript' ) {
167- // Define the new Emmet configuration based on the file mode
168- const emmetConfig = {
169- preview : [ 'html' ] ,
170- markTagPairs : false ,
171- autoRenameTags : true
172- } ;
173- cmInstance . current . setOption ( 'emmet' , emmetConfig ) ;
174- }
175- const oldDoc = cmInstance . current . swapDoc ( docs . current [ file . id ] ) ;
176- if ( prevProps ?. file ) {
177- docs . current [ prevProps . file . id ] = oldDoc ;
178- }
179- cmInstance . current . focus ( ) ;
180-
181- if ( ! prevProps ?. unsavedChanges ) {
182- setTimeout ( ( ) => setUnsavedChanges ( false ) , 400 ) ;
183- }
184-
185- for ( let i = 0 ; i < cmInstance . current . lineCount ( ) ; i += 1 ) {
186- cmInstance . current . removeLineClass (
187- i ,
188- 'background' ,
189- 'line-runtime-error'
190- ) ;
191- }
192- } ,
193- [ file . id ]
194- ) ;
195-
196147 useEffect ( ( ) => {
197148 // close the hinter window once the preference is turned off
198149 if ( ! autocompleteHinter ) hideHinter ( cmInstance . current ) ;
@@ -358,7 +309,6 @@ Editor.propTypes = {
358309 autorefresh : PropTypes . bool . isRequired ,
359310 isPlaying : PropTypes . bool . isRequired ,
360311 theme : PropTypes . string . isRequired ,
361- unsavedChanges : PropTypes . bool . isRequired ,
362312 files : PropTypes . arrayOf (
363313 PropTypes . shape ( {
364314 id : PropTypes . string . isRequired ,
0 commit comments