diff --git a/packages/app/src/pages/public-workspace/[workspaceId]/[pageId].tsx b/packages/app/src/pages/public-workspace/[workspaceId]/[pageId].tsx
index f7b17bb39..d576ab5f2 100644
--- a/packages/app/src/pages/public-workspace/[workspaceId]/[pageId].tsx
+++ b/packages/app/src/pages/public-workspace/[workspaceId]/[pageId].tsx
@@ -3,6 +3,7 @@ import { useAppState } from '@/providers/app-state-provider';
import type { NextPageWithLayout } from '../..//_app';
import dynamic from 'next/dynamic';
+import { useRouter } from 'next/router';
const DynamicBlocksuite = dynamic(() => import('@/components/editor'), {
ssr: false,
});
@@ -11,7 +12,14 @@ const Page: NextPageWithLayout = () => {
const [page, setPage] = useState(null);
const { dataCenter } = useAppState();
console.log('dataCenter: ', dataCenter);
+ const router = useRouter();
+ console.log(router.query.workspaceId);
+ dataCenter
+ .loadPublicWorkspace(router.query.workspaceId as string)
+ .then(data => {
+ console.log(data);
+ });
return (
<>
{workspace && page && (
diff --git a/packages/app/src/pages/public-workspace/[workspaceId]/index.tsx b/packages/app/src/pages/public-workspace/[workspaceId]/index.tsx
index 504e73d16..3be9bb311 100644
--- a/packages/app/src/pages/public-workspace/[workspaceId]/index.tsx
+++ b/packages/app/src/pages/public-workspace/[workspaceId]/index.tsx
@@ -4,12 +4,21 @@ import { PageListHeader } from '@/components/header';
import { ReactElement } from 'react';
import { useTranslation } from '@affine/i18n';
import { useAppState } from '@/providers/app-state-provider';
+import { useRouter } from 'next/router';
const All = () => {
const { pageList } = useAppState();
const { t } = useTranslation();
+ const { dataCenter } = useAppState();
+ const router = useRouter();
+
+ console.log(router.query.workspaceId);
+ dataCenter
+ .loadPublicWorkspace(router.query.workspaceId as string)
+ .then(data => {
+ console.log(data);
+ });
return (
<>
- }>{t('All pages')}
!p.trash)}
showFavoriteTag={true}
diff --git a/packages/data-center/package.json b/packages/data-center/package.json
index d269d9dcd..4dce08d73 100644
--- a/packages/data-center/package.json
+++ b/packages/data-center/package.json
@@ -36,7 +36,6 @@
"ky-universal": "^0.11.0",
"lib0": "^0.2.58",
"swr": "^2.0.0",
- "yjs": "^13.5.44",
"y-protocols": "^1.0.5"
},
"peerDependencies": {
diff --git a/packages/data-center/src/datacenter.ts b/packages/data-center/src/datacenter.ts
index 616345be2..d59f09052 100644
--- a/packages/data-center/src/datacenter.ts
+++ b/packages/data-center/src/datacenter.ts
@@ -13,7 +13,7 @@ import assert from 'assert';
import { getLogger } from './logger';
import { createBlocksuiteWorkspace } from './utils/index.js';
import { MessageCenter } from './message';
-import type { WorkspaceUnit } from './workspace-unit';
+import { WorkspaceUnit } from './workspace-unit';
/**
* @class DataCenter
@@ -153,7 +153,7 @@ export class DataCenter {
/**
* load workspace instance by id
* @param {string} workspaceId workspace id
- * @returns {Promise}
+ * @returns {Promise}
*/
public async loadWorkspace(workspaceId: string) {
const workspaceUnit = this._workspaceUnitCollection.find(workspaceId);
@@ -175,6 +175,29 @@ export class DataCenter {
return workspaceUnit;
}
+ public async loadPublicWorkspace(workspaceId: string) {
+ const workspaceUnit = this._workspaceUnitCollection.find(workspaceId);
+ assert(workspaceUnit, 'Workspace not found');
+ const provider = this.providerMap.get(workspaceUnit.provider);
+ assert(provider);
+ const blocksuiteWorkspace = this._getBlocksuiteWorkspace(workspaceId);
+ await provider.loadPublicWorkspace(blocksuiteWorkspace);
+
+ const workspaceUnitForPublic = new WorkspaceUnit({
+ id: workspaceUnit.id,
+ name: workspaceUnit.name,
+ avatar: workspaceUnit.avatar,
+ owner: workspaceUnit.owner,
+ published: workspaceUnit.published,
+ provider: workspaceUnit.provider,
+ memberCount: workspaceUnit.memberCount,
+ syncMode: workspaceUnit.syncMode,
+ });
+
+ workspaceUnitForPublic.setBlocksuiteWorkspace(blocksuiteWorkspace);
+ return workspaceUnitForPublic;
+ }
+
/**
* get user info by provider id
* @param {string} providerId the provider name of workspace
@@ -206,7 +229,7 @@ export class DataCenter {
/**
* change workspaces meta
* @param {WorkspaceMeta} workspaceMeta workspace meta
- * @param {BlocksuiteWorkspace} workspace workspace instance
+ * @param {WorkspaceUnit} workspace workspace instance
*/
public async updateWorkspaceMeta(
{ name, avatar }: UpdateWorkspaceMetaParams,
@@ -255,12 +278,17 @@ export class DataCenter {
}
}
- public async inviteMember(id: string, email: string) {
- const workspaceInfo = this._workspaceUnitCollection.find(id);
+ /**
+ * invite the new member to the workspace
+ * @param {string} workspaceId workspace id
+ * @param {string} email
+ */
+ public async inviteMember(workspaceId: string, email: string) {
+ const workspaceInfo = this._workspaceUnitCollection.find(workspaceId);
assert(workspaceInfo, 'Workspace not found');
const provider = this.providerMap.get(workspaceInfo.provider);
if (provider) {
- await provider.invite(id, email);
+ await provider.invite(workspaceId, email);
}
}
@@ -380,10 +408,10 @@ export class DataCenter {
* @returns {Promise} blob url
*/
async getBlob(
- workspace: BlocksuiteWorkspace,
+ workspaceUnit: WorkspaceUnit,
id: string
): Promise {
- const blob = await workspace.blobs;
+ const blob = await workspaceUnit.blocksuiteWorkspace?.blobs;
return (await blob?.get(id)) || '';
}
@@ -392,8 +420,8 @@ export class DataCenter {
* @param id
* @returns {Promise} blob url
*/
- async setBlob(workspace: BlocksuiteWorkspace, blob: Blob): Promise {
- const blobStorage = await workspace.blobs;
+ async setBlob(workspace: WorkspaceUnit, blob: Blob): Promise {
+ const blobStorage = await workspace.blocksuiteWorkspace?.blobs;
return (await blobStorage?.set(blob)) || '';
}
diff --git a/packages/data-center/src/provider/affine/affine.ts b/packages/data-center/src/provider/affine/affine.ts
index 3b0161743..1e754e513 100644
--- a/packages/data-center/src/provider/affine/affine.ts
+++ b/packages/data-center/src/provider/affine/affine.ts
@@ -7,33 +7,47 @@ import type {
import type { User } from '../../types';
import { Workspace as BlocksuiteWorkspace } from '@blocksuite/store';
import { BlockSchema } from '@blocksuite/blocks/models';
-import { applyUpdate, encodeStateAsUpdate } from 'yjs';
import { storage } from './storage.js';
import assert from 'assert';
import { WebsocketProvider } from './sync.js';
// import { IndexedDBProvider } from '../local/indexeddb';
-import { getApis, Member } from './apis/index.js';
+import { getApis } from './apis/index.js';
import type { Apis, WorkspaceDetail, Callback } from './apis';
import { setDefaultAvatar } from '../utils.js';
import { MessageCode } from '../../message';
import { token } from './apis/token.js';
+import { WebsocketClient } from './channel';
export interface AffineProviderConstructorParams
extends ProviderConstructorParams {
apis?: Apis;
}
+const {
+ Y: { applyUpdate, encodeStateAsUpdate },
+} = BlocksuiteWorkspace;
+
export class AffineProvider extends BaseProvider {
public id = 'affine';
private _workspacesCache: Map = new Map();
private _onTokenRefresh?: Callback = undefined;
private _wsMap: Map = new Map();
private _apis: Apis;
+ private _channel: WebsocketClient;
// private _idbMap: Map = new Map();
constructor({ apis, ...params }: AffineProviderConstructorParams) {
super(params);
this._apis = apis || getApis();
+ this._channel = new WebsocketClient(
+ `${window.location.protocol === 'https:' ? 'wss' : 'ws'}://${
+ window.location.host
+ }/global/sync/`,
+ this._logger
+ );
+ if (token.isLogin) {
+ this._connectChannel();
+ }
}
override async init() {
@@ -64,6 +78,15 @@ export class AffineProvider extends BaseProvider {
}
}
+ private _connectChannel() {
+ this._channel.connect();
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ this._channel.on('message', (message: any) => {
+ console.log('message', message);
+ });
+ }
+
private _getWebsocketProvider(workspace: BlocksuiteWorkspace) {
const { doc, room } = workspace;
assert(room);
@@ -93,6 +116,11 @@ export class AffineProvider extends BaseProvider {
}
}
+ override async loadPublicWorkspace(blocksuiteWorkspace: BlocksuiteWorkspace) {
+ await this._applyCloudUpdates(blocksuiteWorkspace);
+ return blocksuiteWorkspace;
+ }
+
override async warpWorkspace(workspace: BlocksuiteWorkspace) {
await this._applyCloudUpdates(workspace);
const { room } = workspace;
@@ -207,6 +235,9 @@ export class AffineProvider extends BaseProvider {
}
}
const user = await this._apis.signInWithGoogle?.();
+ if (!this._channel.connected) {
+ this._connectChannel();
+ }
if (!user) {
this._messageCenter.send(MessageCode.loginError);
}
@@ -365,6 +396,8 @@ export class AffineProvider extends BaseProvider {
public override async logout(): Promise {
token.clear();
+ this._channel.disconnect();
+ this._wsMap.forEach(ws => ws.disconnect());
storage.removeItem('token');
}
diff --git a/packages/data-center/src/provider/affine/channel.ts b/packages/data-center/src/provider/affine/channel.ts
new file mode 100644
index 000000000..4dc95004c
--- /dev/null
+++ b/packages/data-center/src/provider/affine/channel.ts
@@ -0,0 +1,53 @@
+import * as websocket from 'lib0/websocket';
+import { Logger } from 'src/types';
+import { token } from './apis/token';
+
+const RECONNECT_INTERVAL_TIME = 5000;
+const MAX_RECONNECT_TIMES = 50;
+
+export class WebsocketClient extends websocket.WebsocketClient {
+ public shouldReconnect = false;
+ private _reconnectInterval: number | null = null;
+ private _logger: Logger;
+ constructor(
+ url: string,
+ logger: Logger,
+ options?: { binaryType: 'arraybuffer' | 'blob' | null }
+ ) {
+ super(url, options);
+ this._logger = logger;
+ this._setupChannel();
+ }
+
+ private _setupChannel() {
+ this.on('connect', () => {
+ this._logger('Affine channel connected');
+ this.shouldReconnect = true;
+ if (this._reconnectInterval) {
+ window.clearInterval(this._reconnectInterval);
+ }
+ });
+
+ this.on('disconnect', ({ error }: { error: Error }) => {
+ if (error) {
+ let times = 0;
+ // Try reconnect if connect error has occurred
+ this._reconnectInterval = window.setInterval(() => {
+ if (this.shouldReconnect && token.isLogin && !this.connected) {
+ try {
+ this.connect();
+ this._logger(`try reconnect channel ${++times} times`);
+ if (times > MAX_RECONNECT_TIMES) {
+ this._logger('reconnect failed, max reconnect times reached');
+ this._reconnectInterval &&
+ window.clearInterval(this._reconnectInterval);
+ }
+ } catch (e) {
+ this._logger('reconnect failed', e);
+ }
+ }
+ }, RECONNECT_INTERVAL_TIME);
+ }
+ });
+ }
+}
diff --git a/packages/data-center/src/provider/base.ts b/packages/data-center/src/provider/base.ts
index 17834abf3..fed862681 100644
--- a/packages/data-center/src/provider/base.ts
+++ b/packages/data-center/src/provider/base.ts
@@ -75,6 +75,15 @@ export class BaseProvider {
return workspace;
}
+ /**
+ * @deprecated Temporary for public workspace
+ * @param blocksuiteWorkspace
+ * @returns
+ */
+ public async loadPublicWorkspace(blocksuiteWorkspace: BlocksuiteWorkspace) {
+ return blocksuiteWorkspace;
+ }
+
/**
* load workspaces
**/
diff --git a/packages/data-center/src/provider/local/indexeddb/indexeddb.ts b/packages/data-center/src/provider/local/indexeddb/indexeddb.ts
index bece021b1..cc79a7d90 100644
--- a/packages/data-center/src/provider/local/indexeddb/indexeddb.ts
+++ b/packages/data-center/src/provider/local/indexeddb/indexeddb.ts
@@ -1,14 +1,19 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import * as idb from 'lib0/indexeddb.js';
import { Observable } from 'lib0/observable.js';
-import type { Doc } from 'yjs';
-import { applyUpdate, encodeStateAsUpdate, transact } from 'yjs';
+import { Workspace as BlocksuiteWorkspace } from '@blocksuite/store';
const customStoreName = 'custom';
const updatesStoreName = 'updates';
const PREFERRED_TRIM_SIZE = 500;
+const {
+ Y: { applyUpdate, transact, encodeStateAsUpdate },
+} = BlocksuiteWorkspace;
+
+type Doc = Parameters[0];
+
const fetchUpdates = async (provider: IndexedDBProvider) => {
const [updatesStore] = idb.transact(provider.db as IDBDatabase, [
updatesStoreName,
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index f268eac27..4844bc6a2 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -144,10 +144,9 @@ importers:
swr: ^2.0.0
typescript: ^4.8.4
y-protocols: ^1.0.5
- yjs: ^13.5.44
dependencies:
- '@blocksuite/blocks': 0.3.1-20230109032243-37ad3ba_yjs@13.5.44
- '@blocksuite/store': 0.3.1-20230109032243-37ad3ba_yjs@13.5.44
+ '@blocksuite/blocks': 0.3.1-20230109032243-37ad3ba
+ '@blocksuite/store': 0.3.1-20230109032243-37ad3ba
debug: 4.3.4
encoding: 0.1.13
firebase: 9.15.0_encoding@0.1.13
@@ -157,7 +156,6 @@ importers:
lib0: 0.2.58
swr: 2.0.0
y-protocols: 1.0.5
- yjs: 13.5.44
devDependencies:
'@playwright/test': 1.29.1
'@types/debug': 4.1.7
@@ -1501,6 +1499,26 @@ packages:
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
dev: true
+ /@blocksuite/blocks/0.3.1-20230109032243-37ad3ba:
+ resolution: {integrity: sha512-UTlbk0Is7TMRBbvUyM2nivbqM/TLwRj1qArMYbOmvDGUNYadWo68cTwv/Ej2WwiKn22q4/4JHryGsv3gTCRz1Q==}
+ dependencies:
+ '@blocksuite/phasor': 0.3.1-20230109032243-37ad3ba
+ '@blocksuite/store': 0.3.1-20230109032243-37ad3ba
+ '@tldraw/intersect': 1.8.0
+ autosize: 5.0.2
+ highlight.js: 11.7.0
+ hotkeys-js: 3.10.1
+ lit: 2.5.0
+ perfect-freehand: 1.2.0
+ quill: 1.3.7
+ quill-cursors: 4.0.0
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+ - yjs
+ dev: false
+
/@blocksuite/blocks/0.3.1-20230109032243-37ad3ba_yjs@13.5.44:
resolution: {integrity: sha512-UTlbk0Is7TMRBbvUyM2nivbqM/TLwRj1qArMYbOmvDGUNYadWo68cTwv/Ej2WwiKn22q4/4JHryGsv3gTCRz1Q==}
dependencies:
@@ -1546,6 +1564,12 @@ packages:
react: 18.2.0
dev: false
+ /@blocksuite/phasor/0.3.1-20230109032243-37ad3ba:
+ resolution: {integrity: sha512-mL1gSQ3rzrjdQSbWPtgyMXpbbl266UUjw26d0aIjkOh+iMMI6rWtmKWDoiDkO7tejIjwSNQ4w5zJOjJRIj+mSA==}
+ peerDependencies:
+ yjs: ^13
+ dev: false
+
/@blocksuite/phasor/0.3.1-20230109032243-37ad3ba_yjs@13.5.44:
resolution: {integrity: sha512-mL1gSQ3rzrjdQSbWPtgyMXpbbl266UUjw26d0aIjkOh+iMMI6rWtmKWDoiDkO7tejIjwSNQ4w5zJOjJRIj+mSA==}
peerDependencies:
@@ -1554,6 +1578,26 @@ packages:
yjs: 13.5.44
dev: false
+ /@blocksuite/store/0.3.1-20230109032243-37ad3ba:
+ resolution: {integrity: sha512-zOUz19jfhuhsUkx9BGEQPZWbPyD/AgX0LB7ShVRdd3YM73x25hD6tPLLz1HEV2b69XokC0P9oSru4aNomm4jkg==}
+ peerDependencies:
+ yjs: ^13
+ dependencies:
+ '@types/flexsearch': 0.7.3
+ '@types/quill': 1.3.10
+ buffer: 6.0.3
+ flexsearch: 0.7.21
+ idb-keyval: 6.2.0
+ ky: 0.33.1
+ lib0: 0.2.58
+ y-protocols: 1.0.5
+ y-webrtc: 10.2.3
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+ dev: false
+
/@blocksuite/store/0.3.1-20230109032243-37ad3ba_yjs@13.5.44:
resolution: {integrity: sha512-zOUz19jfhuhsUkx9BGEQPZWbPyD/AgX0LB7ShVRdd3YM73x25hD6tPLLz1HEV2b69XokC0P9oSru4aNomm4jkg==}
peerDependencies: