diff --git a/apps/frontend/pnpm-lock.yaml b/apps/frontend/pnpm-lock.yaml index 5b99c479b6..13ea2f0ed5 100644 --- a/apps/frontend/pnpm-lock.yaml +++ b/apps/frontend/pnpm-lock.yaml @@ -4981,7 +4981,7 @@ snapshots: debug: 4.3.7 enhanced-resolve: 5.17.1 eslint: 8.0.0 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.8.0(eslint@8.0.0)(typescript@5.0.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.0(eslint@8.0.0)(typescript@5.0.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.0.0))(eslint@8.0.0) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.8.0(eslint@8.0.0)(typescript@5.0.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.0.0) fast-glob: 3.3.2 get-tsconfig: 4.8.1 is-bun-module: 1.2.1 @@ -4994,7 +4994,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@8.8.0(eslint@8.0.0)(typescript@5.0.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.0(eslint@8.0.0)(typescript@5.0.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.0.0))(eslint@8.0.0): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.8.0(eslint@8.0.0)(typescript@5.0.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.0.0): dependencies: debug: 3.2.7 optionalDependencies: @@ -5016,7 +5016,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.0.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.8.0(eslint@8.0.0)(typescript@5.0.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.8.0(eslint@8.0.0)(typescript@5.0.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.0.0))(eslint@8.0.0) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.8.0(eslint@8.0.0)(typescript@5.0.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.0.0) hasown: 2.0.2 is-core-module: 2.15.1 is-glob: 4.0.3 diff --git a/apps/frontend/src/app/collaboration/[id]/page.tsx b/apps/frontend/src/app/collaboration/[id]/page.tsx index ff439397fe..ac664f038a 100644 --- a/apps/frontend/src/app/collaboration/[id]/page.tsx +++ b/apps/frontend/src/app/collaboration/[id]/page.tsx @@ -396,6 +396,7 @@ export default function CollaborationPage(props: CollaborationProps) { localStorage.removeItem("collabId"); localStorage.removeItem("questionDocRefId"); localStorage.removeItem("matchedTopics"); + localStorage.removeItem("editor-language"); // Remove editor language type when session closed }; return ( diff --git a/apps/frontend/src/components/CollaborativeEditor/CollaborativeEditor.tsx b/apps/frontend/src/components/CollaborativeEditor/CollaborativeEditor.tsx index d32f67612d..fab13f68ac 100644 --- a/apps/frontend/src/components/CollaborativeEditor/CollaborativeEditor.tsx +++ b/apps/frontend/src/components/CollaborativeEditor/CollaborativeEditor.tsx @@ -77,6 +77,10 @@ interface Awareness { submitting: boolean; id: number; }; + editorState: { + language: string; + id: number; + }; } export const usercolors = [ @@ -101,8 +105,10 @@ const CollaborativeEditor = forwardRef( ) => { const editorRef = useRef(null); // const providerRef = useRef(null); - const [selectedLanguage, setSelectedLanguage] = useState("Python"); + const [selectedLanguage, setSelectedLanguage] = useState("python"); + const [mounted, setMounted] = useState(false); let sessionEndNotified = false; + let sessionEndTimeout: any; const languageConf = new Compartment(); @@ -113,57 +119,25 @@ const CollaborativeEditor = forwardRef( }); // Referenced: https://codemirror.net/examples/config/#dynamic-configuration - // const autoLanguage = EditorState.transactionExtender.of((tr) => { - // if (!tr.docChanged) return null; - - // const snippet = tr.newDoc.sliceString(0, 100); - - // // Handle code change - // props.onCodeChange(tr.newDoc.toString()); - - // // Test for various language - // const docIsPython = /^\s*(def|class)\s/.test(snippet); - // const docIsJava = /^\s*(class|public\s+static\s+void\s+main)\s/.test( - // snippet - // ); // Java has some problems - // const docIsCpp = /^\s*(#include|namespace|int\s+main)\s/.test(snippet); // Yet to test c++ - // const docIsGo = /^(package|import|func|type|var|const)\s/.test(snippet); - - // let newLanguage; - // let languageType; - // let languageLabel; - - // if (docIsPython) { - // newLanguage = python(); - // languageLabel = "Python"; - // languageType = pythonLanguage; - // } else if (docIsJava) { - // newLanguage = java(); - // languageLabel = "Java"; - // languageType = javaLanguage; - // } else if (docIsGo) { - // newLanguage = go(); - // languageLabel = "Go"; - // languageType = goLanguage; - // } else if (docIsCpp) { - // newLanguage = cpp(); - // languageLabel = "C++"; - // languageType = cppLanguage; - // } else { - // newLanguage = javascript(); // Default to JavaScript - // languageLabel = "JavaScript"; - // languageType = javascriptLanguage; - // } - - // const stateLanguage = tr.startState.facet(language); - // if (languageType == stateLanguage) return null; - - // setSelectedLanguage(languageLabel); - - // return { - // effects: languageConf.reconfigure(newLanguage), - // }; - // }); + const autoLanguage = EditorState.transactionExtender.of((tr) => { + if (!tr.docChanged) return null; + const editorLanguage = localStorage.getItem("editor-language") ?? ""; + let stateIsJs = tr.startState.facet(language) == javascriptLanguage; + let stateIsPython = tr.startState.facet(language) == pythonLanguage; + if ( + (stateIsJs && editorLanguage.toLowerCase() === "javascript") || + (stateIsPython && editorLanguage.toLowerCase() === "python") + ) + return null; + + return { + effects: languageConf.reconfigure( + editorLanguage.toLowerCase() === "javascript" + ? javascript() + : python() + ), + }; + }); const [messageApi, contextHolder] = message.useMessage(); @@ -199,6 +173,7 @@ const CollaborativeEditor = forwardRef( let latestSubmissionId: number = new Date(0).getTime(); let latestExecutingId: number = new Date(0).getTime(); let latestSubmittingId: number = new Date(0).getTime(); + let latestLanguageChangeId: number = new Date(0).getTime(); useImperativeHandle(ref, () => ({ endSession: () => { @@ -219,7 +194,20 @@ const CollaborativeEditor = forwardRef( }, })); - let sessionEndTimeout: any; + useEffect(() => { + localStorage.setItem("editor-language", selectedLanguage); + + if (props.providerRef.current && mounted) { + latestLanguageChangeId = Date.now(); + props.providerRef.current.awareness.setLocalStateField("editorState", { + language: selectedLanguage, + id: latestLanguageChangeId, + }); + success(`Changed Code Editor's language to ${selectedLanguage}`); + } else { + setMounted(true); + } + }, [selectedLanguage]); useEffect(() => { if (process.env.NEXT_PUBLIC_SIGNALLING_SERVICE_URL === undefined) { @@ -309,6 +297,21 @@ const CollaborativeEditor = forwardRef( .getStates() .get(clientID) as Awareness; + // New section to check for changes in language + if ( + state && + state.editorState && + state.editorState.id !== latestLanguageChangeId + ) { + latestSubmissionId = state.editorState.id; + setSelectedLanguage(state.editorState.language); + // if (props.user === state.user.name) { + // console.log("ownself update ownself"); + // } else { + // console.log("others update ownself"); + // } + } + if ( state && state.submissionResultsState && @@ -383,7 +386,7 @@ const CollaborativeEditor = forwardRef( basicSetup, languageConf.of(python()), // languageConf.of(javascript()), - // autoLanguage, + autoLanguage, yCollab(ytext, provider.awareness, { undoManager }), keymap.of([indentWithTab]), codeChangeListener, @@ -410,10 +413,12 @@ const CollaborativeEditor = forwardRef(
Select Language: