diff --git a/src/components/code-editor.tsx b/src/components/code-editor.tsx deleted file mode 100644 index 631c5e1..0000000 --- a/src/components/code-editor.tsx +++ /dev/null @@ -1,163 +0,0 @@ -"use client"; - -import dynamic from "next/dynamic"; -import { getPath } from "@/lib/utils"; -import { highlighter } from "@/lib/shiki"; -import type { editor } from "monaco-editor"; -import { Loading } from "@/components/loading"; -import { shikiToMonaco } from "@shikijs/monaco"; -import type { Monaco } from "@monaco-editor/react"; -import { useCallback, useEffect, useRef } from "react"; -import { useMonacoTheme } from "@/hooks/use-monaco-theme"; -import { connectToLanguageServer } from "@/lib/language-server"; -import { useCodeEditorStore } from "@/store/useCodeEditorStore"; -import type { MonacoLanguageClient } from "monaco-languageclient"; -import { EditorLanguage, EditorLanguageConfig, LanguageServerConfig } from "@prisma/client"; - -// Dynamically import Monaco Editor with SSR disabled -const Editor = dynamic( - async () => { - await import("vscode"); - const monaco = await import("monaco-editor"); - const { loader } = await import("@monaco-editor/react"); - loader.config({ monaco }); - return (await import("@monaco-editor/react")).Editor; - }, - { - ssr: false, - loading: () => , - } -); - -interface CodeEditorProps { - problemId: string; - templates: { language: EditorLanguage; template: string }[]; - editorLanguageConfigs: EditorLanguageConfig[]; - languageServerConfigs: LanguageServerConfig[]; -} - -export default function CodeEditor({ - problemId, - templates, - editorLanguageConfigs, - languageServerConfigs, -}: CodeEditorProps) { - const { - hydrated, - language, - path, - value, - editorConfig, - isLspEnabled, - setEditor, - setPath, - setValue, - } = useCodeEditorStore(); - const { currentTheme } = useMonacoTheme(); - const editorRef = useRef(null); - const monacoLanguageClientRef = useRef(null); - - const valueStorageKey = `value_${problemId}_${language}`; - - useEffect(() => { - const storedValue = localStorage.getItem(valueStorageKey); - if (storedValue !== null) { - setValue(storedValue); - } else { - const currentTemplate = templates.find((t) => t.language === language)?.template ?? ""; - setValue(currentTemplate); - } - }, [valueStorageKey, setValue, templates, language]) - - const handleEditorChange = (value: string | undefined) => { - if (value === undefined) return; - setValue(value); - localStorage.setItem(valueStorageKey, value); - } - - // Connect to LSP only if enabled - const connectLSP = useCallback(async () => { - if (!(isLspEnabled && language && editorRef.current)) return; - - // If there's an existing language client, stop it first - if (monacoLanguageClientRef.current) { - monacoLanguageClientRef.current.stop(); - monacoLanguageClientRef.current = null; - } - - const selectedEditorLanguageConfig = editorLanguageConfigs.find( - (config) => config.language === language - ); - const selectedLanguageServerConfig = languageServerConfigs.find( - (config) => config.language === language - ); - - if (!selectedEditorLanguageConfig || !selectedLanguageServerConfig) return; - - // Create a new language client - try { - const monacoLanguageClient = await connectToLanguageServer( - selectedEditorLanguageConfig, - selectedLanguageServerConfig, - ); - monacoLanguageClientRef.current = monacoLanguageClient; - } catch (error) { - console.error("Failed to connect to LSP:", error); - } - }, [isLspEnabled, language]); - - // Connect to LSP once the editor has mounted - const handleEditorDidMount = useCallback( - async (editor: editor.IStandaloneCodeEditor) => { - editorRef.current = editor; - - const selectedEditorLanguageConfig = editorLanguageConfigs.find( - (config) => config.language === language - ); - setPath(selectedEditorLanguageConfig ? getPath(selectedEditorLanguageConfig) : ""); - - await connectLSP(); - - setEditor(editor); - }, - [connectLSP, setEditor, editorLanguageConfigs, language] - ); - - // Reconnect to the LSP whenever language or lspConfig changes - useEffect(() => { - connectLSP(); - }, [connectLSP]); - - // Cleanup the LSP connection when the component unmounts - useEffect(() => { - return () => { - if (monacoLanguageClientRef.current) { - monacoLanguageClientRef.current.stop(); - monacoLanguageClientRef.current = null; - } - }; - }, []); - - if (!hydrated) { - return ; - } - - const handleEditorWillMount = (monaco: Monaco) => { - shikiToMonaco(highlighter, monaco); - } - - return ( - } - className="h-full w-full py-2" - /> - ); -} diff --git a/src/components/problem-editor.tsx b/src/components/problem-editor.tsx new file mode 100644 index 0000000..a5da2ef --- /dev/null +++ b/src/components/problem-editor.tsx @@ -0,0 +1,58 @@ +"use client"; + +import dynamic from "next/dynamic"; +import { highlighter } from "@/lib/shiki"; +import type { editor } from "monaco-editor"; +import { Loading } from "@/components/loading"; +import { shikiToMonaco } from "@shikijs/monaco"; +import type { Monaco } from "@monaco-editor/react"; +import { useProblemEditor } from "@/hooks/use-problem-editor"; +import { DefaultEditorOptionConfig } from "@/config/editor-option"; + +// Dynamically import Monaco Editor with SSR disabled +const Editor = dynamic( + async () => { + await import("vscode"); + const monaco = await import("monaco-editor"); + const { loader } = await import("@monaco-editor/react"); + loader.config({ monaco }); + return (await import("@monaco-editor/react")).Editor; + }, + { + ssr: false, + loading: () => , + } +); + +export function CodeEditor() { + + const { setEditor, currentLang, currentPath, currentTheme, currentValue, changeValue } = useProblemEditor(); + + const handleBeforeMount = (monaco: Monaco) => { + shikiToMonaco(highlighter, monaco); + }; + + const handleOnMount = (editor: editor.IStandaloneCodeEditor) => { + setEditor(editor); + } + + const handleOnChange = (value: string | undefined) => { + if (value === undefined) return; + changeValue(value); + }; + + return ( + } + className="h-full w-full py-2" + /> + ); +}