🐛(frontend) fix lost content during sync
The tests e2e highlighted a problem where content was lost during synchronization. This bug started to occurs after upgrading Blocknote to 0.41.1 version. It seems to happen only when the initial document is empty and 2 users are collaborating, so before the first minute. We now initialize the editor only when the y-doc has attempted to sync. This should ensure that all updates are applied before the editor is initialized.
This commit is contained in:
@@ -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();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 <Loading />;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<UseCollaborationStore>((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<UseCollaborationStore>((set, get) => ({
|
||||
});
|
||||
},
|
||||
onSynced: ({ state }) => {
|
||||
set({ isSynced: state });
|
||||
set({ isSynced: state, isReady: true });
|
||||
},
|
||||
onClose(data) {
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user