From d417105b688cce41ead3522deaeb660e5c01dcb9 Mon Sep 17 00:00:00 2001 From: bensohh Date: Tue, 12 Nov 2024 22:19:14 +0800 Subject: [PATCH 1/2] Add back localstorage clear method --- apps/frontend/src/components/Header/header.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/frontend/src/components/Header/header.tsx b/apps/frontend/src/components/Header/header.tsx index 387699f5db..ebb9f7c456 100644 --- a/apps/frontend/src/components/Header/header.tsx +++ b/apps/frontend/src/components/Header/header.tsx @@ -70,6 +70,7 @@ const Header = (props: HeaderProps): JSX.Element => { onClick: () => { // Clear away the previously stored jwt token in localstorage deleteToken(); + localStorage.clear(); // Redirect user to login page push("/login"); }, From 87d12999c1ea1b8ee488e63008e0af921af15f11 Mon Sep 17 00:00:00 2001 From: bensohh Date: Tue, 12 Nov 2024 22:20:25 +0800 Subject: [PATCH 2/2] Implement change code functionality for N4 frontend --- apps/frontend/package.json | 2 +- apps/frontend/pnpm-lock.yaml | 6 +- .../src/app/collaboration/[id]/page.tsx | 1 + .../CollaborativeEditor.tsx | 119 +++++++++--------- apps/frontend/src/utils/SelectOptions.ts | 16 +-- 5 files changed, 75 insertions(+), 69 deletions(-) diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 792fc18474..2f2c160b57 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -37,10 +37,10 @@ "yjs": "^13.6.20" }, "devDependencies": { - "@types/codemirror": "^5.60.15", "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.0.1", + "@types/codemirror": "^5.60.15", "@types/jest": "^29.5.14", "@types/node": "^20", "@types/peerjs": "^1.1.0", diff --git a/apps/frontend/pnpm-lock.yaml b/apps/frontend/pnpm-lock.yaml index 413f0c29e3..5b174a23fd 100644 --- a/apps/frontend/pnpm-lock.yaml +++ b/apps/frontend/pnpm-lock.yaml @@ -4902,7 +4902,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 @@ -4915,7 +4915,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: @@ -4937,7 +4937,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 739eac08a6..5523316318 100644 --- a/apps/frontend/src/app/collaboration/[id]/page.tsx +++ b/apps/frontend/src/app/collaboration/[id]/page.tsx @@ -384,6 +384,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: