import React, { useEffect, useRef } from 'react'; import { basicSetup } from 'codemirror'; import { EditorState } from '@codemirror/state'; import { EditorView, keymap } from '@codemirror/view'; import { markdown } from '@codemirror/lang-markdown'; import { defaultKeymap } from '@codemirror/commands'; import { oneDark } from '@codemirror/theme-one-dark'; import { useWorkspace } from '../../contexts/WorkspaceContext'; interface EditorProps { content: string; handleContentChange: (content: string) => void; handleSave: (filePath: string, content: string) => Promise; selectedFile: string; } const Editor: React.FC = ({ content, handleContentChange, handleSave, selectedFile, }) => { const { colorScheme } = useWorkspace(); const editorRef = useRef(null); const viewRef = useRef(null); useEffect(() => { const handleEditorSave = (view: EditorView): boolean => { void handleSave(selectedFile, view.state.doc.toString()); return true; }; const theme = EditorView.theme({ '&': { height: '100%', fontSize: '14px', }, '.cm-scroller': { overflow: 'auto', }, '.cm-gutters': { backgroundColor: colorScheme === 'dark' ? '#1e1e1e' : '#f5f5f5', color: colorScheme === 'dark' ? '#858585' : '#999', border: 'none', }, '.cm-activeLineGutter': { backgroundColor: colorScheme === 'dark' ? '#2c313a' : '#e8e8e8', }, }); if (!editorRef.current) return; const state = EditorState.create({ doc: content, extensions: [ basicSetup, markdown(), EditorView.lineWrapping, keymap.of(defaultKeymap), keymap.of([ { key: 'Ctrl-s', run: handleEditorSave, preventDefault: true, }, ]), EditorView.updateListener.of((update) => { if (update.docChanged) { handleContentChange(update.state.doc.toString()); } }), theme, colorScheme === 'dark' ? oneDark : [], ], }); const view = new EditorView({ state, parent: editorRef.current, }); viewRef.current = view; return () => { view.destroy(); viewRef.current = null; }; // TODO: Refactor // eslint-disable-next-line react-hooks/exhaustive-deps }, [colorScheme, handleContentChange, handleSave, selectedFile]); useEffect(() => { if (viewRef.current && content !== viewRef.current.state.doc.toString()) { viewRef.current.dispatch({ changes: { from: 0, to: viewRef.current.state.doc.length, insert: content, }, }); } }, [content]); return
; }; export default Editor;