diff --git a/libs/components/affine-board/src/Board.tsx b/libs/components/affine-board/src/Board.tsx index 8c521705e7..a28d3580db 100644 --- a/libs/components/affine-board/src/Board.tsx +++ b/libs/components/affine-board/src/Board.tsx @@ -80,7 +80,8 @@ const AffineBoard = ({ ); }, async onChangePage(app, shapes, bindings, assets) { - Promise.all( + await services.api.editorBlock.suspend(workspace, true); + await Promise.all( Object.entries(shapes).map(async ([id, shape]) => { if (shape === undefined) { return services.api.editorBlock.delete({ @@ -120,6 +121,7 @@ const AffineBoard = ({ } }) ); + await services.api.editorBlock.suspend(workspace, false); }, }} /> diff --git a/libs/components/affine-board/src/hooks/use-shapes.ts b/libs/components/affine-board/src/hooks/use-shapes.ts index 23270b6c19..d3ff9e028a 100644 --- a/libs/components/affine-board/src/hooks/use-shapes.ts +++ b/libs/components/affine-board/src/hooks/use-shapes.ts @@ -1,4 +1,4 @@ -import { Editor } from '@toeverything/components/board-shapes'; +import { defaultStyle, Editor } from '@toeverything/components/board-shapes'; import type { TDShape } from '@toeverything/components/board-types'; import type { ReturnEditorBlock } from '@toeverything/datasource/db-service'; import { services } from '@toeverything/datasource/db-service'; @@ -12,7 +12,35 @@ export const useShapes = (workspace: string, rootBlockId: string) => { const [blocks, setBlocks] = useState<{ shapes: [ReturnEditorBlock[]]; }>(); + useEffect(() => { + const unobservesMap = new Map(); + const observeChild = async (childId: string) => { + unobservesMap.set( + childId, + await services.api.editorBlock.observe( + { workspace, id: childId }, + blockData => { + setBlocks(data => { + const blockShapes = data?.shapes?.[0]; + const idx = + blockShapes.findIndex( + s => s.id === blockData.id + ) || -1; + const newBlockShapes = [...blockShapes]; + if (idx > -1) { + newBlockShapes[idx] = blockData; + } else { + newBlockShapes.push(blockData); + } + return { + shapes: [newBlockShapes], + }; + }); + } + ) + ); + }; Promise.all([ services.api.editorBlock .get({ workspace, ids: [rootBlockId] }) @@ -25,6 +53,7 @@ export const useShapes = (workspace: string, rootBlockId: string) => { ids: [childId], }) )?.[0]; + observeChild(childBlock.id); return childBlock; }) ); @@ -47,6 +76,9 @@ export const useShapes = (workspace: string, rootBlockId: string) => { ids: [childId], }) )?.[0]; + if (!unobservesMap.has(childBlock.id)) { + observeChild(childBlock.id); + } return childBlock; }) ).then(shapes => { @@ -65,17 +97,27 @@ export const useShapes = (workspace: string, rootBlockId: string) => { }, [workspace, rootBlockId]); let groupCount = 0; - let blocksShapes = blocks?.shapes[0]?.reduce((acc, block) => { + const blocksShapes = blocks?.shapes[0]?.reduce((acc, block) => { const shapeProps = block.properties.shapeProps?.value ? JSON.parse(block.properties.shapeProps.value) : {}; if (block.type === 'shape') { - acc[block.id] = { ...shapeProps, id: block.id }; + acc[block.id] = { + type: 'rectangle', + size: [0, 0], + point: [0, 0], + parentId: rootBlockId, + ...shapeProps, + id: block.id, + style: { ...defaultStyle }, + workspace, + }; } else { acc[block.id] = Editor.getShape({ point: [groupCount * editorShapeInitSize + 200, 200], id: block.id, size: [editorShapeInitSize, 200], + parentId: rootBlockId, ...shapeProps, affineId: shapeProps.affineId ?? block.id, workspace: block.workspace, diff --git a/libs/datasource/db-service/src/services/base.ts b/libs/datasource/db-service/src/services/base.ts index df0f7133a5..f39b8358d6 100644 --- a/libs/datasource/db-service/src/services/base.ts +++ b/libs/datasource/db-service/src/services/base.ts @@ -35,8 +35,8 @@ export abstract class ServiceBaseClass { name: string, callback: (meta: Map) => void ) { - const db = await this.database.getDatabase(workspace); - db.history.onPush(name, callback); + // const db = await this.database.getDatabase(workspace); + // db.history.onPush(name, callback); } async onHistoryRevoke( @@ -44,8 +44,8 @@ export abstract class ServiceBaseClass { name: string, callback: (meta: Map) => void ) { - const db = await this.database.getDatabase(workspace); - db.history.onPop(name, callback); + // const db = await this.database.getDatabase(workspace); + // db.history.onPop(name, callback); } async undo(workspace: string) { diff --git a/libs/datasource/db-service/src/services/database/index.ts b/libs/datasource/db-service/src/services/database/index.ts index 570de624cb..d4ccbc2ef1 100644 --- a/libs/datasource/db-service/src/services/database/index.ts +++ b/libs/datasource/db-service/src/services/database/index.ts @@ -32,7 +32,7 @@ async function _getCurrentToken() { const _enabled = { demo: [], - AFFiNE: process.env['NX_KECK'] ? ['idb', 'keck'] : ['idb'], + AFFiNE: process.env['NX_KECK'] ? ['keck'] : ['idb'], } as any; async function _getBlockDatabase( diff --git a/libs/datasource/jwt-rpc/src/websocket.ts b/libs/datasource/jwt-rpc/src/websocket.ts index 57cf930856..2e23c92c64 100644 --- a/libs/datasource/jwt-rpc/src/websocket.ts +++ b/libs/datasource/jwt-rpc/src/websocket.ts @@ -65,6 +65,26 @@ export const registerWebsocket = ( let websocket: WebSocket | undefined = undefined; + const broadcastMessage = (buf: ArrayBuffer) => { + if (state === WebSocketState.connected) { + websocket?.send(buf); + } + }; + + const disconnect = () => { + if (websocket != null) { + websocket.close(); + websocket = undefined; + state = WebSocketState.disconnected; + if (resyncInterval !== 0) { + clearInterval(resyncInterval); + } + clearInterval(checkInterval); + } + }; + + const ret = { broadcastMessage, disconnect }; + _getToken( provider.url, token, @@ -126,15 +146,26 @@ export const registerWebsocket = ( if (reconnect <= 0) provider.emit('lost-connection', []); // Start with no reconnect timeout and increase timeout by // using exponential backoff starting with 100ms - setTimeout( - registerWebsocket, - _getTimeout(provider), - provider, - token, - resyncInterval, - reconnect > 0 ? reconnect - 1 : 3, - protocol - ); + setTimeout(() => { + const newRet = registerWebsocket( + provider, + token, + resyncInterval, + reconnect > 0 ? reconnect - 1 : 3, + protocol + ); + ret.broadcastMessage = newRet.broadcastMessage; + ret.disconnect = newRet.disconnect; + }, _getTimeout(provider)); + // setTimeout( + // registerWebsocket, + // _getTimeout(provider), + // provider, + // token, + // resyncInterval, + // reconnect > 0 ? reconnect - 1 : 3, + // protocol + // ); }; websocket.onopen = () => { lastMessageReceived = time.getUnixTime(); @@ -172,14 +203,24 @@ export const registerWebsocket = ( .catch(err => { provider.emit('lost-connection', []); provider.wsUnsuccessfulReconnects++; - setTimeout( - registerWebsocket, - _getTimeout(provider), - provider, - token, - resyncInterval, - reconnect > 0 ? reconnect - 1 : 3 - ); + setTimeout(() => { + const newRet = registerWebsocket( + provider, + token, + resyncInterval, + reconnect > 0 ? reconnect - 1 : 3 + ); + ret.broadcastMessage = newRet.broadcastMessage; + ret.disconnect = newRet.disconnect; + }, _getTimeout(provider)); + // setTimeout( + // registerWebsocket, + // _getTimeout(provider), + // provider, + // token, + // resyncInterval, + // reconnect > 0 ? reconnect - 1 : 3 + // ); }); let resyncInterval = 0; @@ -206,23 +247,5 @@ export const registerWebsocket = ( } }, WEBSOCKET_RECONNECT / 10); - const broadcastMessage = (buf: ArrayBuffer) => { - if (state === WebSocketState.connected) { - websocket?.send(buf); - } - }; - - const disconnect = () => { - if (websocket != null) { - websocket.close(); - websocket = undefined; - state = WebSocketState.disconnected; - if (resyncInterval !== 0) { - clearInterval(resyncInterval); - } - clearInterval(checkInterval); - } - }; - - return { broadcastMessage, disconnect }; + return ret; }; diff --git a/libs/utils/src/lodash.ts b/libs/utils/src/lodash.ts index be22a6dd5c..2ce9556461 100644 --- a/libs/utils/src/lodash.ts +++ b/libs/utils/src/lodash.ts @@ -1,23 +1,24 @@ // eslint-disable-next-line no-restricted-imports export { - debounce, - throttle, cloneDeep, - isEqual, - sum, - has, - forEach, - upperFirst, + countBy, curry, - isFunction, - isString, - isPlainObject, - lowerFirst, - last, - first, - without, + debounce, difference, escape, - countBy, + first, + forEach, + has, + isEqual, + isFunction, + isPlainObject, + isString, + last, + lowerFirst, maxBy, + pickBy, + sum, + throttle, + upperFirst, + without, } from 'lodash-es';