From 2641289b129d5e8f330be3ba251a949e92ffe16c Mon Sep 17 00:00:00 2001 From: Alex Mickelson Date: Fri, 15 Nov 2024 09:05:34 -0700 Subject: [PATCH] fixing authority on server --- .../lecture/[lectureDay]/EditLecture.tsx | 79 ++++++++++++++----- 1 file changed, 59 insertions(+), 20 deletions(-) diff --git a/nextjs/src/app/course/[courseName]/lecture/[lectureDay]/EditLecture.tsx b/nextjs/src/app/course/[courseName]/lecture/[lectureDay]/EditLecture.tsx index 4e60196..1c44e04 100644 --- a/nextjs/src/app/course/[courseName]/lecture/[lectureDay]/EditLecture.tsx +++ b/nextjs/src/app/course/[courseName]/lecture/[lectureDay]/EditLecture.tsx @@ -1,5 +1,4 @@ "use client"; - import { MonacoEditor } from "@/components/editor/MonacoEditor"; import { useLecturesSuspenseQuery, @@ -9,47 +8,63 @@ import { lectureToString, parseLecture, } from "@/services/fileStorage/utils/lectureUtils"; -import { useEffect, useState } from "react"; +import { useCallback, useEffect, useState } from "react"; import LecturePreview from "./LecturePreview"; import EditLectureTitle from "./EditLectureTitle"; import LectureButtons from "./LectureButtons"; import { useCourseContext } from "../../context/courseContext"; import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks"; +import { Lecture } from "@/models/local/lecture"; export default function EditLecture({ lectureDay }: { lectureDay: string }) { - const [_, {dataUpdatedAt}] = useLecturesSuspenseQuery(); - return ( - - ); -} -export function InnerEditLecture({ lectureDay }: { lectureDay: string }) { const { courseName } = useCourseContext(); const [settings] = useLocalCourseSettingsQuery(); - const [weeks] = useLecturesSuspenseQuery(); + const [weeks, { dataUpdatedAt: serverDataUpdatedAt }] = + useLecturesSuspenseQuery(); const updateLecture = useLectureUpdateMutation(); const lecture = weeks .flatMap(({ lectures }) => lectures.map((lecture) => lecture)) .find((l) => l.date === lectureDay); - const startingText = lecture - ? lectureToString(lecture) - : `Name: -Date: ${lectureDay} ---- -`; + const serverVersionOfText = getLectureTextOrDefault(lecture, lectureDay); - const [text, setText] = useState(startingText); + const [text, setText] = useState(serverVersionOfText); + const [updateMonacoKey, setUpdateMonacoKey] = useState(1); const [error, setError] = useState(""); + const [clientDataUpdatedAt, setClientDataUpdatedAt] = + useState(serverDataUpdatedAt); + const clientIsAuthoritative = serverDataUpdatedAt <= clientDataUpdatedAt; + console.log("client it authoritative", clientIsAuthoritative); + + const textUpdate = useCallback((t: string) => { + setText(t); + setClientDataUpdatedAt(Date.now()); + }, []); + useEffect(() => { const delay = 500; const handler = setTimeout(() => { try { const parsed = parseLecture(text); if (!lecture || lectureToString(parsed) !== lectureToString(lecture)) { - console.log("updating lecture"); - updateLecture.mutate({ lecture: parsed, settings, courseName }); + if (clientIsAuthoritative) { + console.log("updating lecture"); + updateLecture.mutate({ lecture: parsed, settings, courseName }); + } else { + if (lecture) { + console.log( + "client not authoritative, updating client with server data" + ); + textUpdate(lectureToString(lecture)); + setUpdateMonacoKey((k) => k + 1); + } else { + console.log( + "client not authoritative, but no lecture on server, this is a bug" + ); + } + } } setError(""); } catch (e: any) { @@ -60,14 +75,26 @@ Date: ${lectureDay} return () => { clearTimeout(handler); }; - }, [courseName, lecture, settings, text, updateLecture]); + }, [ + clientIsAuthoritative, + courseName, + lecture, + settings, + text, + textUpdate, + updateLecture, + ]); return (
- +
{error && error}
@@ -78,3 +105,15 @@ Date: ${lectureDay}
); } + +function getLectureTextOrDefault( + lecture: Lecture | undefined, + lectureDay: string +) { + return lecture + ? lectureToString(lecture) + : `Name: +Date: ${lectureDay} +--- +`; +}