fix collaboration

This commit is contained in:
Philipinho
2025-08-03 18:24:55 -07:00
parent 66a3dad632
commit 63ea2f7663
3 changed files with 48 additions and 45 deletions
+47 -36
View File
@@ -4,6 +4,7 @@ import { IndexeddbPersistence } from "y-indexeddb";
import * as Y from "yjs"; import * as Y from "yjs";
import { import {
HocuspocusProvider, HocuspocusProvider,
onStatusParameters,
onAuthenticationFailedParameters, onAuthenticationFailedParameters,
WebSocketStatus, WebSocketStatus,
} from "@hocuspocus/provider"; } from "@hocuspocus/provider";
@@ -72,7 +73,7 @@ export default function PageEditor({
ydocRef.current = new Y.Doc(); ydocRef.current = new Y.Doc();
} }
const ydoc = ydocRef.current; const ydoc = ydocRef.current;
const [isLocalSynced, setLocalSynced] = useState(false); const [isLocalSynced, setIsLocalSynced] = useState(false);
const [isRemoteSynced, setRemoteSynced] = useState(false); const [isRemoteSynced, setRemoteSynced] = useState(false);
const [yjsConnectionStatus, setYjsConnectionStatus] = useAtom( const [yjsConnectionStatus, setYjsConnectionStatus] = useAtom(
yjsConnectionStatusAtom, yjsConnectionStatusAtom,
@@ -100,29 +101,31 @@ export default function PageEditor({
// Track when collaborative provider is ready and synced // Track when collaborative provider is ready and synced
const [collabReady, setCollabReady] = useState(false); const [collabReady, setCollabReady] = useState(false);
/*
useEffect(() => { useEffect(() => {
if ( if (
remoteProvider?.status === WebSocketStatus.Connected && remoteProvider?.configuration.websocketProvider.status ===
WebSocketStatus.Connected &&
isLocalSynced && isLocalSynced &&
isRemoteSynced isRemoteSynced
) { ) {
setCollabReady(true); setCollabReady(true);
} }
}, [remoteProvider?.status, isLocalSynced, isRemoteSynced]); }, [
*/ remoteProvider?.configuration.websocketProvider.status,
isLocalSynced,
isRemoteSynced,
]);
useEffect(() => { useEffect(() => {
if (!providersRef.current) { if (!providersRef.current) {
const local = new IndexeddbPersistence(documentName, ydoc); const local = new IndexeddbPersistence(documentName, ydoc);
local.on("synced", () => setLocalSynced(true)); local.on("synced", () => setIsLocalSynced(true));
const remote = new HocuspocusProvider({ const remote = new HocuspocusProvider({
name: documentName, name: documentName,
url: collaborationURL, url: collaborationURL,
document: ydoc, document: ydoc,
token: collabQuery?.token, token: collabQuery?.token,
//connect: true,
//preserveConnection: false,
onAuthenticationFailed: (auth: onAuthenticationFailedParameters) => { onAuthenticationFailed: (auth: onAuthenticationFailedParameters) => {
const payload = jwtDecode(collabQuery?.token); const payload = jwtDecode(collabQuery?.token);
const now = Date.now().valueOf() / 1000; const now = Date.now().valueOf() / 1000;
@@ -130,25 +133,28 @@ export default function PageEditor({
if (isTokenExpired) { if (isTokenExpired) {
refetchCollabToken().then((result) => { refetchCollabToken().then((result) => {
if (result.data?.token) { if (result.data?.token) {
remote.disconnect(); remote.configuration.websocketProvider.disconnect();
setTimeout(() => { setTimeout(() => {
remote.configuration.token = result.data.token; remote.configuration.token = result.data.token;
remote.connect(); remote.configuration.websocketProvider.connect();
}, 100); }, 100);
} }
}); });
} }
}, },
//onStatus: (status) => {
// if (status.status === "connected") {
// setYjsConnectionStatus(status.status);
// }
// },
}); });
remote.on("synced", () => setRemoteSynced(true)); remote.on("synced", () => setRemoteSynced(true));
remote.on("disconnect", () => {
setYjsConnectionStatus(WebSocketStatus.Disconnected); const handleSocketStatus = (status: onStatusParameters) => {
}); if (status.status === "connected") {
setYjsConnectionStatus(WebSocketStatus.Connected);
} else if (status.status === "disconnected") {
setYjsConnectionStatus(WebSocketStatus.Disconnected);
}
};
remote.configuration.websocketProvider.on("status", handleSocketStatus);
providersRef.current = { local, remote }; providersRef.current = { local, remote };
setProvidersReady(true); setProvidersReady(true);
} else { } else {
@@ -178,29 +184,29 @@ export default function PageEditor({
*/ */
// Only connect/disconnect on tab/idle, not destroy // Only connect/disconnect on tab/idle, not destroy
/*
useEffect(() => { useEffect(() => {
if (!providersReady || !providersRef.current) return; if (!providersReady || !providersRef.current) return;
const remoteProvider = providersRef.current.remote; const remoteProvider = providersRef.current.remote;
if ( if (
isIdle && isIdle &&
documentState === "hidden" && documentState === "hidden" &&
remoteProvider === WebSocketStatus.Connected remoteProvider.configuration.websocketProvider.status ===
WebSocketStatus.Connected
) { ) {
remoteProvider.disconnect(); remoteProvider.configuration.websocketProvider.disconnect();
setIsCollabReady(false); setIsCollabReady(false);
return; return;
} }
if ( if (
documentState === "visible" && documentState === "visible" &&
remoteProvider.status === WebSocketStatus.Disconnected remoteProvider.configuration.websocketProvider.status ===
WebSocketStatus.Disconnected
) { ) {
resetIdle(); resetIdle();
remoteProvider.connect(); remoteProvider.configuration.websocketProvider.connect();
setTimeout(() => setIsCollabReady(true), 500); setTimeout(() => setIsCollabReady(true), 500);
} }
}, [isIdle, documentState, providersReady, resetIdle]); }, [isIdle, documentState, providersReady, resetIdle]);
*/
const extensions = useMemo(() => { const extensions = useMemo(() => {
if (!remoteProvider || !currentUser?.user) return mainExtensions; if (!remoteProvider || !currentUser?.user) return mainExtensions;
@@ -316,32 +322,37 @@ export default function PageEditor({
setAsideState({ tab: "", isAsideOpen: false }); setAsideState({ tab: "", isAsideOpen: false });
}, [pageId]); }, [pageId]);
/*
useEffect(() => { useEffect(() => {
if (remoteProvider?.status === WebSocketStatus.Connecting) { if (
remoteProvider?.configuration.websocketProvider.status ===
WebSocketStatus.Connecting
) {
const timeout = setTimeout(() => { const timeout = setTimeout(() => {
setYjsConnectionStatus(WebSocketStatus.Disconnected); setYjsConnectionStatus(WebSocketStatus.Disconnected);
}, 5000); }, 5000);
return () => clearTimeout(timeout); return () => clearTimeout(timeout);
} }
}, [remoteProvider?.status]); }, [remoteProvider?.configuration.websocketProvider.status]);
*/
const isSynced = isLocalSynced && isRemoteSynced; const isSynced = isLocalSynced && isRemoteSynced;
/*
useEffect(() => { useEffect(() => {
const collabReadyTimeout = setTimeout(() => { const collabReadyTimeout = setTimeout(() => {
if ( if (
!isCollabReady && !isCollabReady &&
isSynced && isSynced &&
remoteProvider?.status === WebSocketStatus.Connected remoteProvider?.configuration.websocketProvider.status ===
WebSocketStatus.Connected
) { ) {
setIsCollabReady(true); setIsCollabReady(true);
} }
}, 500); }, 500);
return () => clearTimeout(collabReadyTimeout); return () => clearTimeout(collabReadyTimeout);
}, [isRemoteSynced, isLocalSynced, remoteProvider?.status]); }, [
*/ isRemoteSynced,
isLocalSynced,
remoteProvider?.configuration.websocketProvider.status,
]);
useEffect(() => { useEffect(() => {
// Only honor user default page edit mode preference and permissions // Only honor user default page edit mode preference and permissions
@@ -359,18 +370,18 @@ export default function PageEditor({
}, [userPageEditMode, editor, editable]); }, [userPageEditMode, editor, editable]);
const hasConnectedOnceRef = useRef(false); const hasConnectedOnceRef = useRef(false);
const [showStatic, setShowStatic] = useState(false); const [showStatic, setShowStatic] = useState(true);
/*
useEffect(() => { useEffect(() => {
if ( if (
!hasConnectedOnceRef.current && !hasConnectedOnceRef.current &&
remoteProvider?.status === WebSocketStatus.Connected remoteProvider?.configuration.websocketProvider.status ===
WebSocketStatus.Connected
) { ) {
hasConnectedOnceRef.current = true; hasConnectedOnceRef.current = true;
setShowStatic(false); setShowStatic(false);
} }
}, [remoteProvider?.status]);*/ }, [remoteProvider?.configuration.websocketProvider.status]);
if (showStatic) { if (showStatic) {
return ( return (
-1
View File
@@ -58,7 +58,6 @@
"@tiptap/suggestion": "^3.0.9", "@tiptap/suggestion": "^3.0.9",
"@types/qrcode": "^1.5.5", "@types/qrcode": "^1.5.5",
"bytes": "^3.1.2", "bytes": "^3.1.2",
"core": "link:highlight.js/lib/core",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"date-fns": "^4.1.0", "date-fns": "^4.1.0",
"dompurify": "^3.2.6", "dompurify": "^3.2.6",
+1 -8
View File
@@ -136,9 +136,6 @@ importers:
bytes: bytes:
specifier: ^3.1.2 specifier: ^3.1.2
version: 3.1.2 version: 3.1.2
core:
specifier: link:highlight.js/lib/core
version: link:highlight.js/lib/core
cross-env: cross-env:
specifier: ^7.0.3 specifier: ^7.0.3
version: 7.0.3 version: 7.0.3
@@ -683,11 +680,7 @@ importers:
specifier: ^8.24.1 specifier: ^8.24.1
version: 8.24.1(eslint@9.20.1(jiti@1.21.0))(typescript@5.7.3) version: 8.24.1(eslint@9.20.1(jiti@1.21.0))(typescript@5.7.3)
packages/editor-ext: packages/editor-ext: {}
dependencies:
'@tiptap/extension-code-block':
specifier: ^3.0.9
version: 3.0.9(@tiptap/core@3.0.9(@tiptap/pm@3.0.9))(@tiptap/pm@3.0.9)
packages: packages: