diff --git a/packages/data-center/src/provider/affine/affine.ts b/packages/data-center/src/provider/affine/affine.ts index 9fab104f2..5abb451e6 100644 --- a/packages/data-center/src/provider/affine/affine.ts +++ b/packages/data-center/src/provider/affine/affine.ts @@ -22,7 +22,7 @@ import { syncToCloud, } from './utils.js'; import { WorkspaceUnit } from '../../workspace-unit.js'; -import { createBlocksuiteWorkspace } from '../../utils/index.js'; +import { createBlocksuiteWorkspace, applyUpdate } from '../../utils/index.js'; import type { SyncMode } from '../../workspace-unit'; type ChannelMessage = { @@ -37,7 +37,7 @@ export interface AffineProviderConstructorParams } const { - Y: { applyUpdate, encodeStateAsUpdate }, + Y: { encodeStateAsUpdate }, } = BlocksuiteWorkspace; export class AffineProvider extends BaseProvider { @@ -160,12 +160,7 @@ export class AffineProvider extends BaseProvider { const { doc, room: workspaceId } = blocksuiteWorkspace; assert(workspaceId, 'Blocksuite Workspace without room(workspaceId).'); const updates = await this._apis.downloadWorkspace(workspaceId, published); - if (updates && updates.byteLength) { - await new Promise(resolve => { - doc.once('update', resolve); - BlocksuiteWorkspace.Y.applyUpdate(doc, new Uint8Array(updates)); - }); - } + await applyUpdate(blocksuiteWorkspace, new Uint8Array(updates)); } override async loadPublicWorkspace(blocksuiteWorkspace: BlocksuiteWorkspace) { @@ -368,16 +363,11 @@ export class AffineProvider extends BaseProvider { }); const blocksuiteWorkspace = createBlocksuiteWorkspace(id); - - await new Promise(resolve => { - assert(workspaceUnit.blocksuiteWorkspace); - const doc = blocksuiteWorkspace.doc; - doc.once('update', resolve); - applyUpdate( - doc, - encodeStateAsUpdate(workspaceUnit.blocksuiteWorkspace.doc) - ); - }); + assert(workspaceUnit.blocksuiteWorkspace); + await applyUpdate( + blocksuiteWorkspace, + encodeStateAsUpdate(workspaceUnit.blocksuiteWorkspace.doc) + ); await syncToCloud(blocksuiteWorkspace, this._apis.token.refresh); diff --git a/packages/data-center/src/provider/affine/utils.ts b/packages/data-center/src/provider/affine/utils.ts index 7fb62e171..93c2f5600 100644 --- a/packages/data-center/src/provider/affine/utils.ts +++ b/packages/data-center/src/provider/affine/utils.ts @@ -6,6 +6,7 @@ import { createBlocksuiteWorkspace } from '../../utils/index.js'; import type { Apis } from './apis'; import { WebsocketProvider } from './sync.js'; import { setDefaultAvatar } from '../utils.js'; +import { applyUpdate } from '../../utils/index.js'; export const loadWorkspaceUnit = async ( params: WorkspaceUnitCtorParams, @@ -18,13 +19,7 @@ export const loadWorkspaceUnit = async ( workspaceUnit.id, params.published ); - if (updates && updates.byteLength) { - await new Promise(resolve => { - const doc = blocksuiteWorkspace.doc; - doc.once('update', resolve); - BlocksuiteWorkspace.Y.applyUpdate(doc, new Uint8Array(updates)); - }); - } + applyUpdate(blocksuiteWorkspace, new Uint8Array(updates)); const details = await apis.getWorkspaceDetail({ id: workspaceUnit.id }); const owner = details?.owner; diff --git a/packages/data-center/src/provider/local/indexeddb/utils.ts b/packages/data-center/src/provider/local/indexeddb/utils.ts index 10406673f..0a83282a6 100644 --- a/packages/data-center/src/provider/local/indexeddb/utils.ts +++ b/packages/data-center/src/provider/local/indexeddb/utils.ts @@ -1,9 +1,9 @@ import assert from 'assert'; import * as idb from 'lib0/indexeddb.js'; import { Workspace as BlocksuiteWorkspace } from '@blocksuite/store'; +import { applyUpdate } from '../../../utils/index.js'; -const { applyUpdate, encodeStateAsUpdate, mergeUpdates } = - BlocksuiteWorkspace.Y; +const { encodeStateAsUpdate, mergeUpdates } = BlocksuiteWorkspace.Y; export const writeUpdatesToLocal = async ( blocksuiteWorkspace: BlocksuiteWorkspace @@ -34,12 +34,8 @@ export const applyLocalUpdates = async ( const [updatesStore] = idb.transact(db, ['updates']); // , 'readonly') if (updatesStore) { const updates = await idb.getAll(updatesStore); - const doc = blocksuiteWorkspace.doc; - await new Promise(resolve => { - const mergedUpdates = mergeUpdates(updates); - doc.once('update', resolve); - applyUpdate(doc, mergedUpdates); - }); + const mergedUpdates = mergeUpdates(updates); + await applyUpdate(blocksuiteWorkspace, mergedUpdates); } return blocksuiteWorkspace; }; diff --git a/packages/data-center/src/utils/index.ts b/packages/data-center/src/utils/index.ts index 2f2c516d8..9b3489bea 100644 --- a/packages/data-center/src/utils/index.ts +++ b/packages/data-center/src/utils/index.ts @@ -45,3 +45,25 @@ export async function getDefaultHeadImgBlob( } }); } + +export const applyUpdate = async ( + blocksuiteWorkspace: BlocksuiteWorkspace, + updates: Uint8Array +) => { + if (updates && updates.byteLength) { + await new Promise(resolve => { + // FIXME: if we merge two empty doc, there will no update event. + // So we set a timer to cancel update listener. + const doc = blocksuiteWorkspace.doc; + const timer = setTimeout(() => { + doc.off('update', resolve); + resolve(undefined); + }, 1000); + doc.once('update', () => { + clearTimeout(timer); + setTimeout(resolve, 100); + }); + BlocksuiteWorkspace.Y.applyUpdate(doc, new Uint8Array(updates)); + }); + } +};