From 23fb1a5a73cb42e292cf6a30d4e84fc283a60c82 Mon Sep 17 00:00:00 2001 From: Nonumpa Date: Thu, 7 Sep 2023 11:54:31 +0800 Subject: [PATCH] refactor(CollabEditor): get ydoc versions throught api and refetch after user done editing --- components/Collaborate/CollabEditor.js | 33 ++++++++++++++++- components/Collaborate/CollabHistory.js | 47 +++++++++++++++---------- 2 files changed, 60 insertions(+), 20 deletions(-) diff --git a/components/Collaborate/CollabEditor.js b/components/Collaborate/CollabEditor.js index 4cabab45..c32f582b 100644 --- a/components/Collaborate/CollabEditor.js +++ b/components/Collaborate/CollabEditor.js @@ -21,6 +21,8 @@ import useCurrentUser from 'lib/useCurrentUser'; import PlaceholderPlugin from './Placeholder'; import getConfig from 'next/config'; import CollabHistory from './CollabHistory'; +import gql from 'graphql-tag'; +import { useQuery } from '@apollo/react-hooks'; const { publicRuntimeConfig: { PUBLIC_COLLAB_SERVER_URL }, @@ -81,6 +83,17 @@ const colors = [ const color = colors[Math.floor(Math.random() * colors.length)]; +const YDOC_VERSIONS_QUERY = gql` + query GetYdocVersions($id: String!) { + GetYdoc(id: $id) { + versions { + createdAt + snapshot + } + } + } +`; + const Editor = ({ provider, currentUser, className, innerRef, onUnmount }) => { useEffect(() => { // console.log('editor mount'); @@ -139,6 +152,14 @@ const CollabEditor = ({ article }) => { // onTranscribe setup provider for both Editor and CollabHistory to use. // And, to avoid duplicated connection, provider will be destroyed(close connection) when Editor unmounted. const [provider, setProvider] = useState(null); + const { loading, data: getYdocData, refetch } = useQuery( + YDOC_VERSIONS_QUERY, + { + variables: { id: article.id }, + ssr: false, // No need to fetch on server + } + ); + const versionList = getYdocData?.GetYdoc?.versions || []; const onTranscribe = () => { if (!currentUser) { @@ -187,6 +208,10 @@ const CollabEditor = ({ article }) => { // TODO: listen textChanged event? article.text = text; } + + // refetch to get latest versionList + refetch({ id: article.id }); + setShowEditor(false); }; @@ -238,7 +263,13 @@ const CollabEditor = ({ article }) => { {t`Edit`} ) : ( - isSynced && + isSynced && + !loading && ( + + ) )} )} diff --git a/components/Collaborate/CollabHistory.js b/components/Collaborate/CollabHistory.js index 359744f4..dd18d066 100644 --- a/components/Collaborate/CollabHistory.js +++ b/components/Collaborate/CollabHistory.js @@ -54,11 +54,11 @@ const useStyles = makeStyles(theme => ({ const renderVersion = (editorview, version, prevVersion) => { const transaction = editorview.state.tr.setMeta(ySyncPluginKey, { - snapshot: Y.decodeSnapshot(version.snapshot), + snapshot: Y.decodeSnapshot(Buffer.from(version.snapshot, 'base64')), prevSnapshot: prevVersion == null ? Y.emptySnapshot - : Y.decodeSnapshot(prevVersion.snapshot), + : Y.decodeSnapshot(Buffer.from(prevVersion.snapshot, 'base64')), }); editorview.dispatch(transaction); }; @@ -74,15 +74,15 @@ const renderVersion = (editorview, version, prevVersion) => { * Should render `Versions` after `editorLoaded`, * `Versions` will default render latest version * @param {EditorView} editorView - * @param {Y.Doc} ydoc - * @param {(version: Y.Snapshot, index: number) => void} onSelect - called when version selected + * @param {Array<{snapshot: string, createdAt: string}>} versionList + * @param {(version: {snapshot: string, createdAt: string}, index: number) => void} onSelect - called when version selected */ -const Versions = ({ editorView, ydoc, onSelect }) => { - const versions = ydoc.getArray('versions'); - const defaultVIdx = versions.length - 1; +const Versions = ({ editorView, versionList, onSelect }) => { + const defaultVIdx = versionList.length - 1; const [selectedVersion, setSelectedVersion] = useState(null); useEffect(() => { + if (defaultVIdx === -1) return; // default select latest version selectAndRender(defaultVIdx); }, [defaultVIdx, selectAndRender]); @@ -90,12 +90,12 @@ const Versions = ({ editorView, ydoc, onSelect }) => { const selectAndRender = useCallback( reverseIdx => { setSelectedVersion(reverseIdx); - const version = versions.get(reverseIdx); - const prevVersion = reverseIdx > 0 ? versions.get(reverseIdx - 1) : null; + const version = versionList[reverseIdx]; + const prevVersion = reverseIdx > 0 ? versionList[reverseIdx - 1] : null; onSelect(version, reverseIdx); renderVersion(editorView, version, prevVersion); }, - [versions, onSelect, editorView] + [editorView, versionList, onSelect] ); const toggleChanged = (event, reverseIdx) => { @@ -107,7 +107,7 @@ const Versions = ({ editorView, ydoc, onSelect }) => { return ( <> {t`Versions`} - {versions.length > 0 ? ( + {versionList.length > 0 ? ( { onChange={toggleChanged} style={{ overflow: 'auto' }} > - {versions.map((v, i) => { + {versionList.map((v, i) => { // list version in reverse order - const reverseIdx = versions.length - 1 - i; - const version = versions.get(reverseIdx); + const reverseIdx = versionList.length - 1 - i; + const version = versionList[reverseIdx]; return ( - {new Date(version.date).toLocaleString()} + {new Date(version.createdAt).toLocaleString()} ); })} @@ -135,7 +135,7 @@ const Versions = ({ editorView, ydoc, onSelect }) => { }; const CustomModalContent = forwardRef(function CustomModalContent( - { ydoc, onClose }, + { ydoc, onClose, versionList }, ref ) { const editor = useRef(ref); @@ -169,8 +169,9 @@ const CustomModalContent = forwardRef(function CustomModalContent( editorView={editor.current.view} ydoc={ydoc} onSelect={version => - setVersionTitle(new Date(version.date).toLocaleString()) + setVersionTitle(new Date(version.createdAt).toLocaleString()) } + versionList={versionList} /> )} @@ -189,7 +190,11 @@ const CustomModalContent = forwardRef(function CustomModalContent( ); }); -const CollabHistory = ({ ydoc }) => { +/** + * @param {Y.Doc} ydoc + * @param {Array<{snapshot: string, createdAt: string}>} versionList + */ +const CollabHistory = ({ ydoc, versionList }) => { const [open, setOpen] = useState(false); const handleOpen = () => setOpen(true); const handleClose = () => setOpen(false); @@ -207,7 +212,11 @@ const CollabHistory = ({ ydoc }) => { {t`History`} - +