From 08a19ae240c51175768ad25b92f9a2a598ebd5f5 Mon Sep 17 00:00:00 2001 From: lawvs <18554747+lawvs@users.noreply.github.com> Date: Thu, 22 Sep 2022 22:38:59 +0800 Subject: [PATCH 1/3] fix: ignore node_modules watcher --- apps/ligo-virgo/webpack.config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ligo-virgo/webpack.config.js b/apps/ligo-virgo/webpack.config.js index 3b0750fade..a960c2a54e 100644 --- a/apps/ligo-virgo/webpack.config.js +++ b/apps/ligo-virgo/webpack.config.js @@ -203,10 +203,10 @@ module.exports = function (webpackConfig) { new BundleAnalyzerPlugin({ analyzerMode: 'static' }), ].filter(Boolean); - // Workaround for webpack infinite recompile errors config.watchOptions = { // followSymlinks: false, - ignored: ['**/*.css'], + // Ignore css to workaround webpack infinite recompile errors + ignored: ['**/node_modules', '**/*.css'], }; return config; From 0a8780a9d41d43ee592080b9e3c036e0187a8f7c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 23 Sep 2022 00:32:16 +0000 Subject: [PATCH 2/3] feat(i18n): new translations --- libs/datasource/i18n/src/resources/index.ts | 22 ++++++++++++++ libs/datasource/i18n/src/resources/sr.json | 27 +++++++++++++++++ .../i18n/src/resources/zh-Hant.json | 29 +++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 libs/datasource/i18n/src/resources/sr.json create mode 100644 libs/datasource/i18n/src/resources/zh-Hant.json diff --git a/libs/datasource/i18n/src/resources/index.ts b/libs/datasource/i18n/src/resources/index.ts index 1d3e875c60..b0fd2469b0 100644 --- a/libs/datasource/i18n/src/resources/index.ts +++ b/libs/datasource/i18n/src/resources/index.ts @@ -3,6 +3,8 @@ // To overwrite this, please overwrite download.ts import en from './en.json'; import zh_Hans from './zh-Hans.json'; +import zh_Hant from './zh-Hant.json'; +import sr from './sr.json'; export const LOCALES = [ { @@ -25,4 +27,24 @@ export const LOCALES = [ completeRate: 1, res: zh_Hans, }, + { + id: 1000016012, + name: 'Traditional Chinese', + tag: 'zh-Hant', + originalName: '繁體中文', + flagEmoji: '🇭🇰', + base: false, + completeRate: 1, + res: zh_Hant, + }, + { + id: 1000034005, + name: 'Serbian', + tag: 'sr', + originalName: 'српски', + flagEmoji: '🇷🇸', + base: false, + completeRate: 0.9166666666666666, + res: sr, + }, ] as const; diff --git a/libs/datasource/i18n/src/resources/sr.json b/libs/datasource/i18n/src/resources/sr.json new file mode 100644 index 0000000000..edc6c32f2c --- /dev/null +++ b/libs/datasource/i18n/src/resources/sr.json @@ -0,0 +1,27 @@ +{ + "// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.": "", + "Clear Workspace": "Očisti radni prostor", + "ComingSoon": "Podešavanja za izgled dolaze", + "Comment": "Komentar", + "Copy Page Link": "Kopiraj link stranice", + "Delete": "Obriši", + "Duplicate Page": "Dupliraj stranicu", + "Export As HTML": "Izvezi kao HTML", + "Export As Markdown": "Izvezi kao Markdown", + "Export As PDF (Unsupported)": "Izvezi kao PDF (nepodržano)", + "Export Workspace": "Izvezi radnu površinu", + "Import Workspace": "Poboljšaj radnu površinu", + "Language": "Jezik", + "Last edited by": "Zadnju promenu uradio {{ime}}", + "Layout": "Izgled", + "Logout": "Odjava", + "Settings": "Podešavanja", + "Share": "Podeli", + "Sync to Disk": "Sinhroniziraj sa diskom", + "Turn into": "Promeni u", + "WarningTips": { + "DoNotStore": "AFFiNE je u stanju aktivnog razvoja i trenutna verzija je NESTABILNA. Molimo vas, NEMOJTE čuvati informacije ili podatke.", + "IsNotLocalWorkspace": "Dobrodošli u AFFiNE demo. Da bi započeli proces čuvanja promena možete kliknuti SINHRONIZUJ SA DISKOM.", + "IsNotfsApiSupported": "Dobrodošli u AFFiNE demo. Da bi započeli proces čuvanja promena možete SINHRONIZOVATI NA DISK sa poslednjom verzijom pretraživača tipa Chromium, kao što su Chrome/Edge." + } +} diff --git a/libs/datasource/i18n/src/resources/zh-Hant.json b/libs/datasource/i18n/src/resources/zh-Hant.json new file mode 100644 index 0000000000..483613b43d --- /dev/null +++ b/libs/datasource/i18n/src/resources/zh-Hant.json @@ -0,0 +1,29 @@ +{ + "// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.": "", + "Add A Below Block": "在下方新添塊", + "Clear Workspace": "清空工作區", + "ComingSoon": "自定義佈局功能即將與您見面", + "Comment": "評論", + "Copy Page Link": "拷貝頁面鏈接", + "Delete": "刪除", + "Divide Here As A New Group": "從此地劃分成新組", + "Duplicate Page": "複製界面", + "Export As HTML": "導出 HTML", + "Export As Markdown": "以 Markdown 導出", + "Export As PDF (Unsupported)": "導出為 PDF(即將可用)", + "Export Workspace": "導出 Workspace", + "Import Workspace": "導入 Workspace", + "Language": "語言", + "Last edited by": "最後編輯者為 {{name}}", + "Layout": "佈局", + "Logout": "退出登錄", + "Settings": "設置", + "Share": "分享", + "Sync to Disk": "同步到磁盤", + "Turn into": "轉換為", + "WarningTips": { + "DoNotStore": "我們正在積極開發 AFFiNE,目前版本尚不穩定,請避免存儲信息或數據。", + "IsNotLocalWorkspace": "歡迎來到 AFFiNE 演示界面。您可以通過「同步到磁盤」來保存更改。", + "IsNotfsApiSupported": "歡迎進入AFFINE演示!使用最新版本的基於 Chromium 內核的瀏覽器如Chrome/Edge,您可以通過「同步到磁盤」來保存更改" + } +} From 5ac0f91efcdd9e019d225067df13f8606a645a9b Mon Sep 17 00:00:00 2001 From: alt0 Date: Fri, 23 Sep 2022 19:14:23 +0800 Subject: [PATCH 3/3] fix: sync bug --- libs/components/affine-board/src/Board.tsx | 4 +- .../affine-board/src/hooks/use-shapes.ts | 48 +++++++++- .../db-service/src/services/base.ts | 8 +- .../db-service/src/services/database/index.ts | 2 +- libs/datasource/jwt-rpc/src/websocket.ts | 95 ++++++++++++------- libs/utils/src/lodash.ts | 31 +++--- 6 files changed, 128 insertions(+), 60 deletions(-) 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';