Skip to content

Commit 3e5bcf9

Browse files
committed
⬆️(y-provider) update hocuspocus to 3.2.5
The last version of Blocknote seems to have a conflict with hocuspocus 2.15.2, it is a good moment to upgrade to hocuspocus 3.2.5.
1 parent fe24c00 commit 3e5bcf9

File tree

16 files changed

+124
-112
lines changed

16 files changed

+124
-112
lines changed

renovate.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
"groupName": "ignored js dependencies",
2525
"matchManagers": ["npm"],
2626
"matchPackageNames": [
27-
"@hocuspocus/provider",
28-
"@hocuspocus/server",
2927
"docx",
3028
"fetch-mock",
3129
"node",

src/frontend/apps/impress/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"@fontsource/material-icons": "5.2.7",
3636
"@gouvfr-lasuite/integration": "1.0.3",
3737
"@gouvfr-lasuite/ui-kit": "0.16.2",
38-
"@hocuspocus/provider": "2.15.2",
38+
"@hocuspocus/provider": "3.3.0",
3939
"@mantine/core": "8.3.4",
4040
"@mantine/hooks": "8.3.4",
4141
"@openfun/cunningham-react": "3.2.3",

src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ import { useTranslation } from 'react-i18next';
1717
import * as Y from 'yjs';
1818

1919
import { Box, TextErrors } from '@/components';
20-
import { Doc, useIsCollaborativeEditable } from '@/docs/doc-management';
20+
import {
21+
Doc,
22+
useIsCollaborativeEditable,
23+
useProviderStore,
24+
} from '@/docs/doc-management';
2125
import { useAuth } from '@/features/auth';
2226

2327
import {
@@ -79,9 +83,10 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
7983
const { user } = useAuth();
8084
const { setEditor } = useEditorStore();
8185
const { t } = useTranslation();
86+
const { isSynced } = useProviderStore();
8287

8388
const { isEditable, isLoading } = useIsCollaborativeEditable(doc);
84-
const isConnectedToCollabServer = provider.isSynced;
89+
const isConnectedToCollabServer = isSynced;
8590
const readOnly = !doc.abilities.partial_update || !isEditable || isLoading;
8691
const isDeletedDoc = !!doc.deleted_at;
8792

src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { useEffect, useState } from 'react';
44
import { css } from 'styled-components';
55
import * as Y from 'yjs';
66

7-
import { Box, Text, TextErrors } from '@/components';
7+
import { Box, Loading, Text, TextErrors } from '@/components';
88
import { DocHeader, DocVersionHeader } from '@/docs/doc-header/';
99
import {
1010
Doc,
@@ -27,8 +27,9 @@ export const DocEditor = ({ doc, versionId }: DocEditorProps) => {
2727
const isVersion = !!versionId && typeof versionId === 'string';
2828
const { provider } = useProviderStore();
2929

30+
// TODO: Use skeleton instead of loading
3031
if (!provider) {
31-
return null;
32+
return <Loading />;
3233
}
3334

3435
return (

src/frontend/apps/impress/src/features/docs/doc-management/stores/useProviderStore.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { CloseEvent } from '@hocuspocus/common';
12
import { HocuspocusProvider, WebSocketStatus } from '@hocuspocus/provider';
23
import * as Y from 'yjs';
34
import { create } from 'zustand';
@@ -13,16 +14,20 @@ export interface UseCollaborationStore {
1314
destroyProvider: () => void;
1415
provider: HocuspocusProvider | undefined;
1516
isConnected: boolean;
17+
isSynced: boolean;
1618
hasLostConnection: boolean;
1719
resetLostConnection: () => void;
1820
}
1921

2022
const defaultValues = {
2123
provider: undefined,
2224
isConnected: false,
25+
isSynced: false,
2326
hasLostConnection: false,
2427
};
2528

29+
type ExtendedCloseEvent = CloseEvent & { wasClean: boolean };
30+
2631
export const useProviderStore = create<UseCollaborationStore>((set, get) => ({
2732
...defaultValues,
2833
createProvider: (wsUrl, storeId, initialDoc) => {
@@ -38,6 +43,12 @@ export const useProviderStore = create<UseCollaborationStore>((set, get) => ({
3843
url: wsUrl,
3944
name: storeId,
4045
document: doc,
46+
onDisconnect(data) {
47+
// Attempt to reconnect if the disconnection was clean (initiated by the client or server)
48+
if ((data.event as ExtendedCloseEvent).wasClean) {
49+
provider.connect();
50+
}
51+
},
4152
onStatus: ({ status }) => {
4253
set((state) => {
4354
const nextConnected = status === WebSocketStatus.Connected;
@@ -50,6 +61,21 @@ export const useProviderStore = create<UseCollaborationStore>((set, get) => ({
5061
};
5162
});
5263
},
64+
onSynced: ({ state }) => {
65+
set({ isSynced: state });
66+
},
67+
onClose(data) {
68+
/**
69+
* Handle the "Reset Connection" event from the server
70+
* This is triggered when the server wants to reset the connection
71+
* for clients in the room.
72+
* A disconnect is made automatically but it takes time to be triggered,
73+
* so we force the disconnection here.
74+
*/
75+
if (data.event.code === 1000) {
76+
provider.disconnect();
77+
}
78+
},
5379
});
5480

5581
set({

src/frontend/apps/impress/src/features/docs/doc-share/api/useUpdateDocAccess.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66

77
import { APIError, errorCauses, fetchAPI } from '@/api';
88
import { Access, KEY_DOC, KEY_LIST_DOC, Role } from '@/docs/doc-management';
9-
import { useBroadcastStore } from '@/stores';
109

1110
import { KEY_LIST_DOC_ACCESSES } from './useDocAccesses';
1211

@@ -45,7 +44,6 @@ type UseUpdateDocAccessOptions = UseMutationOptions<
4544

4645
export const useUpdateDocAccess = (options?: UseUpdateDocAccessOptions) => {
4746
const queryClient = useQueryClient();
48-
const { broadcast } = useBroadcastStore();
4947

5048
return useMutation<Access, APIError, UpdateDocAccessProps>({
5149
mutationFn: updateDocAccess,
@@ -58,12 +56,10 @@ export const useUpdateDocAccess = (options?: UseUpdateDocAccessOptions) => {
5856
queryKey: [KEY_DOC],
5957
});
6058

61-
// Broadcast to every user connected to the document
62-
broadcast(`${KEY_DOC}-${variables.docId}`);
63-
6459
void queryClient.invalidateQueries({
6560
queryKey: [KEY_LIST_DOC],
6661
});
62+
6763
if (options?.onSuccess) {
6864
void options.onSuccess(data, variables, onMutateResult, context);
6965
}

src/frontend/apps/impress/src/pages/docs/[id]/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ const DocPage = ({ id }: DocProps) => {
147147
}
148148

149149
addTask(`${KEY_DOC}-${doc.id}`, () => {
150-
void queryClient.resetQueries({
150+
void queryClient.invalidateQueries({
151151
queryKey: [KEY_DOC, { id: doc.id }],
152152
});
153153
});

src/frontend/servers/y-provider/__tests__/collaborationResetConnections.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ describe('Server Tests', () => {
4545

4646
test('POST /collaboration/api/reset-connections?room=[ROOM_ID] with correct API key should reset connections', async () => {
4747
const closeConnectionsMock = vi
48-
.spyOn(hocuspocusServer, 'closeConnections')
48+
.spyOn(hocuspocusServer.hocuspocus, 'closeConnections')
4949
.mockResolvedValue();
5050

5151
const app = initApp();

src/frontend/servers/y-provider/__tests__/getDocumentConnectionInfoHandler.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,11 @@ describe('Server Tests', () => {
7070
});
7171

7272
test('POST /collaboration/api/get-connections?room=[ROOM_ID] returns connection info, session key existing', async () => {
73-
const document = await hocuspocusServer.createDocument(
73+
const document = await hocuspocusServer.hocuspocus.createDocument(
7474
'test-room',
7575
{},
7676
uuid(),
77-
{ isAuthenticated: true, readOnly: false, requiresAuthentication: true },
77+
{ isAuthenticated: true, readOnly: false },
7878
{},
7979
);
8080

@@ -138,11 +138,11 @@ describe('Server Tests', () => {
138138
});
139139

140140
test('POST /collaboration/api/get-connections?room=[ROOM_ID] returns connection info, session key not existing', async () => {
141-
const document = await hocuspocusServer.createDocument(
141+
const document = await hocuspocusServer.hocuspocus.createDocument(
142142
'test-room',
143143
{},
144144
uuid(),
145-
{ isAuthenticated: true, readOnly: false, requiresAuthentication: true },
145+
{ isAuthenticated: true, readOnly: false },
146146
{},
147147
);
148148

@@ -206,11 +206,11 @@ describe('Server Tests', () => {
206206
});
207207

208208
test('POST /collaboration/api/get-connections?room=[ROOM_ID] returns connection info, session key not existing, read only connection', async () => {
209-
const document = await hocuspocusServer.createDocument(
209+
const document = await hocuspocusServer.hocuspocus.createDocument(
210210
'test-room',
211211
{},
212212
uuid(),
213-
{ isAuthenticated: true, readOnly: false, requiresAuthentication: true },
213+
{ isAuthenticated: true, readOnly: false },
214214
{},
215215
);
216216

0 commit comments

Comments
 (0)