From 362b6f42388f80fa8eb566ed0784d6b0ade6a2c4 Mon Sep 17 00:00:00 2001 From: alt0 Date: Wed, 11 Jan 2023 20:43:19 +0800 Subject: [PATCH 1/6] fix: multiple add same workspace error --- packages/data-center/src/workspace-unit-collection.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/data-center/src/workspace-unit-collection.ts b/packages/data-center/src/workspace-unit-collection.ts index 58770e2122..f385cecdca 100644 --- a/packages/data-center/src/workspace-unit-collection.ts +++ b/packages/data-center/src/workspace-unit-collection.ts @@ -61,7 +61,8 @@ export class WorkspaceUnitCollection { const add = (workspace: WorkspaceUnitCtorParams) => { if (this._workspaceUnitMap.has(workspace.id)) { - throw new Error(`Duplicate workspace id.`); + // FIXME: multiple add same workspace + return; } const workspaceUnit = new WorkspaceUnit(workspace); From bda94bb8658b0987a1602a99f0ae6fa1d569e5df Mon Sep 17 00:00:00 2001 From: alt0 Date: Wed, 11 Jan 2023 20:46:04 +0800 Subject: [PATCH 2/6] fix: public workspace don't need to check permission --- packages/data-center/src/datacenter.ts | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/data-center/src/datacenter.ts b/packages/data-center/src/datacenter.ts index d59f090526..8d860ac18c 100644 --- a/packages/data-center/src/datacenter.ts +++ b/packages/data-center/src/datacenter.ts @@ -176,22 +176,21 @@ export class DataCenter { } public async loadPublicWorkspace(workspaceId: string) { - const workspaceUnit = this._workspaceUnitCollection.find(workspaceId); - assert(workspaceUnit, 'Workspace not found'); - const provider = this.providerMap.get(workspaceUnit.provider); + // FIXME: hard code for public workspace + const provider = this.providerMap.get('affine'); 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, + id: workspaceId, + name: blocksuiteWorkspace.meta.name, + avatar: blocksuiteWorkspace.meta.avatar, + owner: undefined, + published: true, + provider: 'affine', + memberCount: 1, + syncMode: 'core', }); workspaceUnitForPublic.setBlocksuiteWorkspace(blocksuiteWorkspace); From 2d1fd3a083589fe787534f255f202e5466c7d5af Mon Sep 17 00:00:00 2001 From: alt0 Date: Wed, 11 Jan 2023 20:53:53 +0800 Subject: [PATCH 3/6] fix: add param for download public workspace --- packages/data-center/src/provider/affine/affine.ts | 9 ++++++--- .../data-center/src/provider/affine/apis/workspace.ts | 6 +++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/data-center/src/provider/affine/affine.ts b/packages/data-center/src/provider/affine/affine.ts index b0544b1bc7..a3142b74ac 100644 --- a/packages/data-center/src/provider/affine/affine.ts +++ b/packages/data-center/src/provider/affine/affine.ts @@ -104,10 +104,13 @@ export class AffineProvider extends BaseProvider { return ws; } - private async _applyCloudUpdates(blocksuiteWorkspace: BlocksuiteWorkspace) { + private async _applyCloudUpdates( + blocksuiteWorkspace: BlocksuiteWorkspace, + published = false + ) { const { doc, room: workspaceId } = blocksuiteWorkspace; assert(workspaceId, 'Blocksuite Workspace without room(workspaceId).'); - const updates = await this._apis.downloadWorkspace(workspaceId); + const updates = await this._apis.downloadWorkspace(workspaceId, published); if (updates && updates.byteLength) { await new Promise(resolve => { doc.once('update', resolve); @@ -117,7 +120,7 @@ export class AffineProvider extends BaseProvider { } override async loadPublicWorkspace(blocksuiteWorkspace: BlocksuiteWorkspace) { - await this._applyCloudUpdates(blocksuiteWorkspace); + await this._applyCloudUpdates(blocksuiteWorkspace, true); return blocksuiteWorkspace; } diff --git a/packages/data-center/src/provider/affine/apis/workspace.ts b/packages/data-center/src/provider/affine/apis/workspace.ts index 8bdc25b21f..6151946660 100644 --- a/packages/data-center/src/provider/affine/apis/workspace.ts +++ b/packages/data-center/src/provider/affine/apis/workspace.ts @@ -169,7 +169,11 @@ export async function leaveWorkspace({ id }: LeaveWorkspaceParams) { } export async function downloadWorkspace( - workspaceId: string + workspaceId: string, + published = false ): Promise { + if (published) { + return bareClient.get(`api/workspace/${workspaceId}/doc`).arrayBuffer(); + } return client.get(`api/workspace/${workspaceId}/doc`).arrayBuffer(); } From 15bdd2f31e37e681410d3eace5cb30d823560752 Mon Sep 17 00:00:00 2001 From: alt0 Date: Wed, 11 Jan 2023 20:55:08 +0800 Subject: [PATCH 4/6] fix: getBlocksuiteWorkspace remove check --- packages/data-center/src/datacenter.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/data-center/src/datacenter.ts b/packages/data-center/src/datacenter.ts index 8d860ac18c..c15861223e 100644 --- a/packages/data-center/src/datacenter.ts +++ b/packages/data-center/src/datacenter.ts @@ -122,8 +122,8 @@ export class DataCenter { * @param {string} workspaceId workspace id */ private _getBlocksuiteWorkspace(workspaceId: string) { - const workspaceInfo = this._workspaceUnitCollection.find(workspaceId); - assert(workspaceInfo, 'Workspace not found'); + // const workspaceInfo = this._workspaceUnitCollection.find(workspaceId); + // assert(workspaceInfo, 'Workspace not found'); return ( // this._workspaceInstances.get(workspaceId) || createBlocksuiteWorkspace(workspaceId) From fc2a5879bd526e5fd2f76bd499ea4f6c74a913db Mon Sep 17 00:00:00 2001 From: MingLiang Wang Date: Wed, 11 Jan 2023 20:57:56 +0800 Subject: [PATCH 5/6] feat: add channel for get new affine list --- .../data-center/src/provider/affine/affine.ts | 71 ++++++++++++++----- .../src/provider/affine/channel.ts | 19 +++-- 2 files changed, 69 insertions(+), 21 deletions(-) diff --git a/packages/data-center/src/provider/affine/affine.ts b/packages/data-center/src/provider/affine/affine.ts index a3142b74ac..c116492099 100644 --- a/packages/data-center/src/provider/affine/affine.ts +++ b/packages/data-center/src/provider/affine/affine.ts @@ -11,12 +11,13 @@ import { storage } from './storage.js'; import assert from 'assert'; import { WebsocketProvider } from './sync.js'; // import { IndexedDBProvider } from '../local/indexeddb'; -import { getApis } from './apis/index.js'; +import { getApis, Workspace } 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'; +import { SyncMode } from '../../workspace-unit'; export interface AffineProviderConstructorParams extends ProviderConstructorParams { @@ -33,21 +34,12 @@ export class AffineProvider extends BaseProvider { private _onTokenRefresh?: Callback = undefined; private _wsMap: Map = new Map(); private _apis: Apis; - private _channel: WebsocketClient; + 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() { @@ -76,14 +68,59 @@ export class AffineProvider extends BaseProvider { } else { storage.setItem('token', this._apis.token.refresh); } + + if (token.isLogin) { + this._connectChannel(); + } } private _connectChannel() { - this._channel.connect(); + if (!this._channel) { + this._channel = new WebsocketClient( + `${window.location.protocol === 'https:' ? 'wss' : 'ws'}://${ + window.location.host + }/api/global/sync/`, + this._logger, + { + params: { + token: this._apis.token.refresh, + }, + } + ); + } + this._channel.on('message', this.handlerAffineListMessage); + } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - this._channel.on('message', (message: any) => { - console.log('message', message); + private handlerAffineListMessage({ + ws_details, + metadata, + }: { + ws_list: Workspace[]; + ws_details: Record; + metadata: Record; + }) { + Object.entries(ws_details).forEach(([id, detail]) => { + const { name, avatar } = metadata[id]; + assert(name); + const workspace = { + name: name, + avatar, + owner: { + name: detail.owner.name, + id: detail.owner.id, + email: detail.owner.email, + avatar: detail.owner.avatar_url, + }, + published: detail.public, + memberCount: detail.member_count, + provider: 'affine', + syncMode: 'core' as SyncMode, + }; + if (this._workspaces.get(id)) { + this._workspaces.update(id, workspace); + } else { + this._workspaces.add({ id, ...workspace }); + } }); } @@ -237,7 +274,7 @@ export class AffineProvider extends BaseProvider { } } const user = await this._apis.signInWithGoogle?.(); - if (!this._channel.connected) { + if (!this._channel?.connected) { this._connectChannel(); } if (!user) { @@ -397,7 +434,7 @@ export class AffineProvider extends BaseProvider { public override async logout(): Promise { token.clear(); - this._channel.disconnect(); + 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 index 8d4ae85b09..1503a8b450 100644 --- a/packages/data-center/src/provider/affine/channel.ts +++ b/packages/data-center/src/provider/affine/channel.ts @@ -1,6 +1,7 @@ -import websocket from 'lib0/websocket'; +import * as websocket from 'lib0/websocket'; import { Logger } from 'src/types'; import { token } from './apis/token'; +import * as url from 'lib0/url'; const RECONNECT_INTERVAL_TIME = 5000; const MAX_RECONNECT_TIMES = 50; @@ -10,11 +11,21 @@ export class WebsocketClient extends websocket.WebsocketClient { private _reconnectInterval: number | null = null; private _logger: Logger; constructor( - url: string, + serverUrl: string, logger: Logger, - options?: { binaryType: 'arraybuffer' | 'blob' | null } + options?: ConstructorParameters[1] & { + params: Record; + } ) { - super(url, options); + const params = options?.params || {}; + // ensure that url is always ends with / + while (serverUrl[serverUrl.length - 1] === '/') { + serverUrl = serverUrl.slice(0, serverUrl.length - 1); + } + const encodedParams = url.encodeQueryParams(params); + const newUrl = + serverUrl + '/' + (encodedParams.length === 0 ? '' : '?' + encodedParams); + super(newUrl, options); this._logger = logger; this._setupChannel(); } From 932f5f02c44cd494bc40256b36597825afd6affc Mon Sep 17 00:00:00 2001 From: MingLiang Wang Date: Wed, 11 Jan 2023 21:10:31 +0800 Subject: [PATCH 6/6] feat: fix users list --- packages/data-center/src/provider/affine/affine.ts | 12 ++++++------ .../data-center/src/provider/affine/apis/user.ts | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/data-center/src/provider/affine/affine.ts b/packages/data-center/src/provider/affine/affine.ts index c116492099..41b93b7dc2 100644 --- a/packages/data-center/src/provider/affine/affine.ts +++ b/packages/data-center/src/provider/affine/affine.ts @@ -403,13 +403,13 @@ export class AffineProvider extends BaseProvider { workspace_id: string, email: string ): Promise { - const user = await this._apis.getUserByEmail({ workspace_id, email }); - return user + const users = await this._apis.getUserByEmail({ workspace_id, email }); + return users?.length ? { - id: user.id, - name: user.name, - avatar: user.avatar_url, - email: user.email, + id: users[0].id, + name: users[0].name, + avatar: users[0].avatar_url, + email: users[0].email, } : null; } diff --git a/packages/data-center/src/provider/affine/apis/user.ts b/packages/data-center/src/provider/affine/apis/user.ts index 2848a9b673..58ede20fc3 100644 --- a/packages/data-center/src/provider/affine/apis/user.ts +++ b/packages/data-center/src/provider/affine/apis/user.ts @@ -15,7 +15,7 @@ export interface User { export async function getUserByEmail( params: GetUserByEmailParams -): Promise { +): Promise { const searchParams = new URLSearchParams({ ...params }); - return client.get('api/user', { searchParams }).json(); + return client.get('api/user', { searchParams }).json(); }