diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-visibility.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-visibility.spec.ts
index b39cb5c0..24cf4bfb 100644
--- a/src/frontend/apps/e2e/__tests__/app-impress/doc-visibility.spec.ts
+++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-visibility.spec.ts
@@ -7,6 +7,7 @@ import {
keyCloakSignIn,
verifyDocName,
} from './utils-common';
+import { writeInEditor } from './utils-editor';
import { addNewMember, connectOtherUserToDoc } from './utils-share';
import { createRootSubPage } from './utils-sub-pages';
@@ -151,18 +152,15 @@ test.describe('Doc Visibility: Restricted', () => {
await verifyDocName(page, docTitle);
- await page
- .locator('.ProseMirror')
- .locator('.bn-block-outer')
- .last()
- .fill('Hello World');
+ await writeInEditor({ page, text: 'Hello World' });
const docUrl = page.url();
- const { otherBrowserName, otherPage } = await connectOtherUserToDoc({
- browserName,
- docUrl,
- });
+ const { otherBrowserName, otherPage, cleanup } =
+ await connectOtherUserToDoc({
+ browserName,
+ docUrl,
+ });
await expect(
otherPage.getByText('Insufficient access rights to view the document.'),
@@ -178,6 +176,8 @@ test.describe('Doc Visibility: Restricted', () => {
await expect(otherPage.getByText('Hello World')).toBeVisible({
timeout: 10000,
});
+
+ await cleanup();
});
});
diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx
index 80188c33..3b6a67ad 100644
--- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx
+++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx
@@ -83,10 +83,9 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
const { user } = useAuth();
const { setEditor } = useEditorStore();
const { t } = useTranslation();
- const { isSynced } = useProviderStore();
+ const { isSynced: isConnectedToCollabServer } = useProviderStore();
const { isEditable, isLoading } = useIsCollaborativeEditable(doc);
- const isConnectedToCollabServer = isSynced;
const readOnly = !doc.abilities.partial_update || !isEditable || isLoading;
const isDeletedDoc = !!doc.deleted_at;
diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx
index c405fe96..7ad0a941 100644
--- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx
+++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx
@@ -25,10 +25,10 @@ interface DocEditorProps {
export const DocEditor = ({ doc, versionId }: DocEditorProps) => {
const { isDesktop } = useResponsiveStore();
const isVersion = !!versionId && typeof versionId === 'string';
- const { provider } = useProviderStore();
+ const { provider, isReady } = useProviderStore();
// TODO: Use skeleton instead of loading
- if (!provider) {
+ if (!provider || !isReady) {
return ;
}
diff --git a/src/frontend/apps/impress/src/features/docs/doc-management/stores/useProviderStore.tsx b/src/frontend/apps/impress/src/features/docs/doc-management/stores/useProviderStore.tsx
index 6971c614..33eb3d6a 100644
--- a/src/frontend/apps/impress/src/features/docs/doc-management/stores/useProviderStore.tsx
+++ b/src/frontend/apps/impress/src/features/docs/doc-management/stores/useProviderStore.tsx
@@ -14,6 +14,7 @@ export interface UseCollaborationStore {
destroyProvider: () => void;
provider: HocuspocusProvider | undefined;
isConnected: boolean;
+ isReady: boolean;
isSynced: boolean;
hasLostConnection: boolean;
resetLostConnection: () => void;
@@ -22,6 +23,7 @@ export interface UseCollaborationStore {
const defaultValues = {
provider: undefined,
isConnected: false,
+ isReady: false,
isSynced: false,
hasLostConnection: false,
};
@@ -46,14 +48,18 @@ export const useProviderStore = create((set, get) => ({
onDisconnect(data) {
// Attempt to reconnect if the disconnection was clean (initiated by the client or server)
if ((data.event as ExtendedCloseEvent).wasClean) {
- provider.connect();
+ void provider.connect();
}
},
+ onAuthenticationFailed() {
+ set({ isReady: true });
+ },
onStatus: ({ status }) => {
set((state) => {
const nextConnected = status === WebSocketStatus.Connected;
return {
isConnected: nextConnected,
+ isReady: state.isReady || status === WebSocketStatus.Disconnected,
hasLostConnection:
state.isConnected && !nextConnected
? true
@@ -62,7 +68,7 @@ export const useProviderStore = create((set, get) => ({
});
},
onSynced: ({ state }) => {
- set({ isSynced: state });
+ set({ isSynced: state, isReady: true });
},
onClose(data) {
/**