mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-25 10:22:55 +08:00
Merge branch 'feat/cloud-sync-saika' into feat/datacenter-dev
This commit is contained in:
@@ -11,7 +11,7 @@ const EDITOR_VERSION = enableDebugLocal
|
|||||||
|
|
||||||
const profileTarget = {
|
const profileTarget = {
|
||||||
ac: '100.85.73.88:12001',
|
ac: '100.85.73.88:12001',
|
||||||
dev: '192.168.65.20:3000',
|
dev: '100.77.180.48:11001',
|
||||||
local: '127.0.0.1:3000',
|
local: '127.0.0.1:3000',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -96,12 +96,7 @@ export class DataCenter {
|
|||||||
'There is no provider. You should add provider first.'
|
'There is no provider. You should add provider first.'
|
||||||
);
|
);
|
||||||
|
|
||||||
const workspaceMeta = await this._mainProvider.createWorkspaceInfo(params);
|
const workspaceUnit = await this._mainProvider.createWorkspace(params);
|
||||||
|
|
||||||
const workspace = createBlocksuiteWorkspace(workspaceMeta.id);
|
|
||||||
|
|
||||||
await this._mainProvider.createWorkspace(workspace, workspaceMeta);
|
|
||||||
const workspaceUnit = this._workspaceUnitCollection.find(workspaceMeta.id);
|
|
||||||
return workspaceUnit;
|
return workspaceUnit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +164,9 @@ export class DataCenter {
|
|||||||
this._workspaceInstances.set(workspaceId, workspace);
|
this._workspaceInstances.set(workspaceId, workspace);
|
||||||
await provider.warpWorkspace(workspace);
|
await provider.warpWorkspace(workspace);
|
||||||
this._workspaceUnitCollection.workspaces.forEach(workspaceUnit => {
|
this._workspaceUnitCollection.workspaces.forEach(workspaceUnit => {
|
||||||
workspaceUnit.setBlocksuiteWorkspace(null);
|
const provider = this.providerMap.get(workspaceUnit.provider);
|
||||||
|
assert(provider);
|
||||||
|
provider.closeWorkspace(workspaceUnit.id);
|
||||||
});
|
});
|
||||||
workspaceUnit.setBlocksuiteWorkspace(workspace);
|
workspaceUnit.setBlocksuiteWorkspace(workspace);
|
||||||
return workspaceUnit;
|
return workspaceUnit;
|
||||||
@@ -322,55 +319,33 @@ export class DataCenter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _transWorkspaceProvider(
|
public async enableProvider(
|
||||||
workspace: BlocksuiteWorkspace,
|
workspaceUnit: WorkspaceUnit,
|
||||||
providerId: string
|
providerId = 'affine'
|
||||||
) {
|
) {
|
||||||
assert(workspace.room, 'No workspace id');
|
if (workspaceUnit.provider === providerId) {
|
||||||
const workspaceInfo = this._workspaceUnitCollection.find(workspace.room);
|
|
||||||
assert(workspaceInfo, 'Workspace not found');
|
|
||||||
if (workspaceInfo.provider === providerId) {
|
|
||||||
this._logger('Workspace provider is same');
|
this._logger('Workspace provider is same');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const currentProvider = this.providerMap.get(workspaceInfo.provider);
|
const provider = this.providerMap.get(providerId);
|
||||||
assert(currentProvider, 'Provider not found');
|
assert(provider);
|
||||||
const newProvider = this.providerMap.get(providerId);
|
const newWorkspaceUnit = await provider.extendWorkspace(workspaceUnit);
|
||||||
assert(newProvider, `provide '${providerId}' is not registered`);
|
|
||||||
this._logger(`create ${providerId} workspace: `, workspaceInfo.name);
|
|
||||||
const newWorkspaceInfo = await newProvider.createWorkspaceInfo({
|
|
||||||
name: workspaceInfo.name,
|
|
||||||
// avatar: workspaceInfo.avatar,
|
|
||||||
});
|
|
||||||
const newWorkspace = createBlocksuiteWorkspace(newWorkspaceInfo.id);
|
|
||||||
// TODO optimize this function
|
|
||||||
await newProvider.createWorkspace(newWorkspace, {
|
|
||||||
...newWorkspaceInfo,
|
|
||||||
name: workspaceInfo.name,
|
|
||||||
avatar: workspaceInfo.avatar,
|
|
||||||
});
|
|
||||||
|
|
||||||
assert(newWorkspace, 'Create workspace failed');
|
// Currently we only allow enable one provider, so after enable new provider,
|
||||||
this._logger(
|
// delete the old workspace from its provider.
|
||||||
`update workspace data from ${workspaceInfo.provider} to ${providerId}`
|
const oldProvider = this.providerMap.get(workspaceUnit.provider);
|
||||||
);
|
assert(oldProvider);
|
||||||
await newProvider.assign(newWorkspace, workspace);
|
await oldProvider.deleteWorkspace(workspaceUnit.id);
|
||||||
assert(newWorkspace, 'Create workspace failed');
|
|
||||||
await currentProvider.deleteWorkspace(workspace.room);
|
return newWorkspaceUnit;
|
||||||
return newWorkspace.room;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable workspace cloud
|
* Enable workspace cloud
|
||||||
* @param {string} id ID of workspace.
|
* @param {string} id ID of workspace.
|
||||||
*/
|
*/
|
||||||
public async enableWorkspaceCloud(workspace: WorkspaceUnit) {
|
public async enableWorkspaceCloud(workspaceUnit: WorkspaceUnit) {
|
||||||
assert(workspace?.id, 'No workspace to enable cloud');
|
return this.enableProvider(workspaceUnit);
|
||||||
assert(workspace.blocksuiteWorkspace);
|
|
||||||
return await this._transWorkspaceProvider(
|
|
||||||
workspace.blocksuiteWorkspace,
|
|
||||||
'affine'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import type {
|
|||||||
} from '../base';
|
} from '../base';
|
||||||
import type { User } from '../../types';
|
import type { User } from '../../types';
|
||||||
import { Workspace as BlocksuiteWorkspace } from '@blocksuite/store';
|
import { Workspace as BlocksuiteWorkspace } from '@blocksuite/store';
|
||||||
import { BlockSchema } from '@blocksuite/blocks/models';
|
|
||||||
import { storage } from './storage.js';
|
import { storage } from './storage.js';
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
import { WebsocketProvider } from './sync.js';
|
import { WebsocketProvider } from './sync.js';
|
||||||
@@ -14,10 +13,17 @@ import { WebsocketProvider } from './sync.js';
|
|||||||
import { getApis, Workspace } from './apis/index.js';
|
import { getApis, Workspace } from './apis/index.js';
|
||||||
import type { Apis, WorkspaceDetail, Callback } from './apis';
|
import type { Apis, WorkspaceDetail, Callback } from './apis';
|
||||||
import { setDefaultAvatar } from '../utils.js';
|
import { setDefaultAvatar } from '../utils.js';
|
||||||
import { MessageCode } from '../../message';
|
import { MessageCode } from '../../message/index.js';
|
||||||
import { token } from './apis/token.js';
|
import { token } from './apis/token.js';
|
||||||
import { WebsocketClient } from './channel';
|
import { WebsocketClient } from './channel';
|
||||||
import { SyncMode } from '../../workspace-unit';
|
import {
|
||||||
|
loadWorkspaceUnit,
|
||||||
|
createWorkspaceUnit,
|
||||||
|
syncToCloud,
|
||||||
|
} from './utils.js';
|
||||||
|
import { WorkspaceUnit } from '../../workspace-unit.js';
|
||||||
|
import { createBlocksuiteWorkspace, applyUpdate } from '../../utils/index.js';
|
||||||
|
import type { SyncMode } from '../../workspace-unit';
|
||||||
|
|
||||||
type ChannelMessage = {
|
type ChannelMessage = {
|
||||||
ws_list: Workspace[];
|
ws_list: Workspace[];
|
||||||
@@ -31,7 +37,7 @@ export interface AffineProviderConstructorParams
|
|||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
Y: { applyUpdate, encodeStateAsUpdate },
|
Y: { encodeStateAsUpdate },
|
||||||
} = BlocksuiteWorkspace;
|
} = BlocksuiteWorkspace;
|
||||||
|
|
||||||
export class AffineProvider extends BaseProvider {
|
export class AffineProvider extends BaseProvider {
|
||||||
@@ -95,13 +101,13 @@ export class AffineProvider extends BaseProvider {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
this._channel.on('message', (msg: ChannelMessage) => {
|
this._channel.on('message', (msg: ChannelMessage) => {
|
||||||
this.handlerAffineListMessage(msg);
|
this._handlerAffineListMessage(msg);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private handlerAffineListMessage({ ws_details, metadata }: ChannelMessage) {
|
private _handlerAffineListMessage({ ws_details, metadata }: ChannelMessage) {
|
||||||
this._logger('receive server message');
|
this._logger('receive server message');
|
||||||
Object.entries(ws_details).forEach(([id, detail]) => {
|
Object.entries(ws_details).forEach(async ([id, detail]) => {
|
||||||
const { name, avatar } = metadata[id];
|
const { name, avatar } = metadata[id];
|
||||||
assert(name);
|
assert(name);
|
||||||
const workspace = {
|
const workspace = {
|
||||||
@@ -121,7 +127,11 @@ export class AffineProvider extends BaseProvider {
|
|||||||
if (this._workspaces.get(id)) {
|
if (this._workspaces.get(id)) {
|
||||||
this._workspaces.update(id, workspace);
|
this._workspaces.update(id, workspace);
|
||||||
} else {
|
} else {
|
||||||
this._workspaces.add({ id, ...workspace });
|
const workspaceUnit = await loadWorkspaceUnit(
|
||||||
|
{ id, ...workspace },
|
||||||
|
this._apis
|
||||||
|
);
|
||||||
|
this._workspaces.add(workspaceUnit);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -147,17 +157,10 @@ export class AffineProvider extends BaseProvider {
|
|||||||
blocksuiteWorkspace: BlocksuiteWorkspace,
|
blocksuiteWorkspace: BlocksuiteWorkspace,
|
||||||
published = false
|
published = false
|
||||||
) {
|
) {
|
||||||
const { doc, room: workspaceId } = blocksuiteWorkspace;
|
const { room: workspaceId } = blocksuiteWorkspace;
|
||||||
assert(workspaceId, 'Blocksuite Workspace without room(workspaceId).');
|
assert(workspaceId, 'Blocksuite Workspace without room(workspaceId).');
|
||||||
const updates = await this._apis.downloadWorkspace(workspaceId, published);
|
const updates = await this._apis.downloadWorkspace(workspaceId, published);
|
||||||
if (updates && updates.byteLength) {
|
await applyUpdate(blocksuiteWorkspace, new Uint8Array(updates));
|
||||||
await new Promise(resolve => {
|
|
||||||
doc.once('update', () => {
|
|
||||||
setTimeout(resolve, 100);
|
|
||||||
});
|
|
||||||
BlocksuiteWorkspace.Y.applyUpdate(doc, new Uint8Array(updates));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override async loadPublicWorkspace(blocksuiteWorkspace: BlocksuiteWorkspace) {
|
override async loadPublicWorkspace(blocksuiteWorkspace: BlocksuiteWorkspace) {
|
||||||
@@ -194,79 +197,25 @@ export class AffineProvider extends BaseProvider {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const workspacesList = await this._apis.getWorkspaces();
|
const workspacesList = await this._apis.getWorkspaces();
|
||||||
const workspaces: WorkspaceMeta0[] = workspacesList.map(w => {
|
const workspaceUnits = await Promise.all(
|
||||||
return {
|
workspacesList.map(w => {
|
||||||
...w,
|
return loadWorkspaceUnit(
|
||||||
published: w.public,
|
{
|
||||||
memberCount: 0,
|
id: w.id,
|
||||||
name: '',
|
name: '',
|
||||||
provider: 'affine',
|
avatar: undefined,
|
||||||
syncMode: 'core',
|
owner: undefined,
|
||||||
};
|
published: w.public,
|
||||||
});
|
memberCount: 1,
|
||||||
const workspaceInstances = workspaces.map(({ id }) => {
|
provider: 'affine',
|
||||||
const workspace =
|
syncMode: 'core',
|
||||||
this._workspacesCache.get(id) ||
|
},
|
||||||
new BlocksuiteWorkspace({
|
this._apis
|
||||||
room: id,
|
);
|
||||||
}).register(BlockSchema);
|
})
|
||||||
this._workspacesCache.set(id, workspace);
|
);
|
||||||
if (workspace) {
|
this._workspaces.add(workspaceUnits);
|
||||||
return new Promise<BlocksuiteWorkspace>(resolve => {
|
return workspaceUnits;
|
||||||
this._apis.downloadWorkspace(id).then(data => {
|
|
||||||
applyUpdate(workspace.doc, new Uint8Array(data));
|
|
||||||
resolve(workspace);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return Promise.resolve(null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
(await Promise.all(workspaceInstances)).forEach((workspace, i) => {
|
|
||||||
if (workspace) {
|
|
||||||
workspaces[i] = {
|
|
||||||
...workspaces[i],
|
|
||||||
name: workspace.meta.name,
|
|
||||||
avatar: workspace.meta.avatar,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const getDetailList = workspacesList.map(w => {
|
|
||||||
const { id } = w;
|
|
||||||
return new Promise<{ id: string; detail: WorkspaceDetail | null }>(
|
|
||||||
resolve => {
|
|
||||||
this._apis.getWorkspaceDetail({ id }).then(data => {
|
|
||||||
resolve({ id, detail: data || null });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
const ownerList = await Promise.all(getDetailList);
|
|
||||||
(await Promise.all(ownerList)).forEach(detail => {
|
|
||||||
if (detail) {
|
|
||||||
const { id, detail: workspaceDetail } = detail;
|
|
||||||
if (workspaceDetail) {
|
|
||||||
const { owner, member_count } = workspaceDetail;
|
|
||||||
const currentWorkspace = workspaces.find(w => w.id === id);
|
|
||||||
if (currentWorkspace) {
|
|
||||||
currentWorkspace.owner = {
|
|
||||||
id: owner.id,
|
|
||||||
name: owner.name,
|
|
||||||
avatar: owner.avatar_url,
|
|
||||||
email: owner.email,
|
|
||||||
};
|
|
||||||
currentWorkspace.memberCount = member_count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
workspaces.forEach(workspace => {
|
|
||||||
this._workspaces.add(workspace);
|
|
||||||
});
|
|
||||||
|
|
||||||
return workspaces;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override async auth() {
|
override async auth() {
|
||||||
@@ -353,52 +302,29 @@ export class AffineProvider extends BaseProvider {
|
|||||||
// return workspace;
|
// return workspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async createWorkspaceInfo(
|
public override async createWorkspace(
|
||||||
meta: CreateWorkspaceInfoParams
|
meta: CreateWorkspaceInfoParams
|
||||||
): Promise<WorkspaceMeta0> {
|
): Promise<WorkspaceUnit | undefined> {
|
||||||
const { id } = await this._apis.createWorkspace(meta);
|
const { id } = await this._apis.createWorkspace(meta);
|
||||||
|
|
||||||
const workspaceInfo: WorkspaceMeta0 = {
|
const workspaceUnit = await createWorkspaceUnit({
|
||||||
|
id,
|
||||||
name: meta.name,
|
name: meta.name,
|
||||||
id: id,
|
avatar: undefined,
|
||||||
published: false,
|
|
||||||
avatar: '',
|
|
||||||
owner: await this.getUserInfo(),
|
owner: await this.getUserInfo(),
|
||||||
syncMode: 'core',
|
|
||||||
memberCount: 1,
|
|
||||||
provider: 'affine',
|
|
||||||
};
|
|
||||||
return workspaceInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async createWorkspace(
|
|
||||||
blocksuiteWorkspace: BlocksuiteWorkspace,
|
|
||||||
meta: WorkspaceMeta0
|
|
||||||
): Promise<BlocksuiteWorkspace | undefined> {
|
|
||||||
const workspaceId = blocksuiteWorkspace.room;
|
|
||||||
assert(workspaceId, 'Blocksuite Workspace without room(workspaceId).');
|
|
||||||
this._logger('Creating affine workspace');
|
|
||||||
|
|
||||||
this._applyCloudUpdates(blocksuiteWorkspace);
|
|
||||||
this.linkLocal(blocksuiteWorkspace);
|
|
||||||
|
|
||||||
const workspaceInfo: WorkspaceMeta0 = {
|
|
||||||
name: meta.name,
|
|
||||||
id: workspaceId,
|
|
||||||
published: false,
|
published: false,
|
||||||
avatar: '',
|
|
||||||
owner: undefined,
|
|
||||||
syncMode: 'core',
|
|
||||||
memberCount: 1,
|
memberCount: 1,
|
||||||
provider: 'affine',
|
provider: 'affine',
|
||||||
};
|
syncMode: 'core',
|
||||||
|
});
|
||||||
|
|
||||||
if (!blocksuiteWorkspace.meta.avatar) {
|
await syncToCloud(
|
||||||
await setDefaultAvatar(blocksuiteWorkspace);
|
workspaceUnit.blocksuiteWorkspace!,
|
||||||
workspaceInfo.avatar = blocksuiteWorkspace.meta.avatar;
|
this._apis.token.refresh
|
||||||
}
|
);
|
||||||
this._workspaces.add(workspaceInfo);
|
this._workspaces.add(workspaceUnit);
|
||||||
return blocksuiteWorkspace;
|
|
||||||
|
return workspaceUnit;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async publish(id: string, isPublish: boolean): Promise<void> {
|
public override async publish(id: string, isPublish: boolean): Promise<void> {
|
||||||
@@ -420,22 +346,36 @@ export class AffineProvider extends BaseProvider {
|
|||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async assign(
|
public override async extendWorkspace(
|
||||||
to: BlocksuiteWorkspace,
|
workspaceUnit: WorkspaceUnit
|
||||||
from: BlocksuiteWorkspace
|
): Promise<WorkspaceUnit> {
|
||||||
): Promise<BlocksuiteWorkspace> {
|
const { id } = await this._apis.createWorkspace({
|
||||||
assert(to.room, 'Blocksuite Workspace without room(workspaceId).');
|
name: workspaceUnit.name,
|
||||||
const ws = this._getWebsocketProvider(to);
|
|
||||||
applyUpdate(to.doc, encodeStateAsUpdate(from.doc));
|
|
||||||
// TODO: upload blobs and make sure doc is synced
|
|
||||||
await new Promise<void>((resolve, reject) => {
|
|
||||||
ws.once('synced', () => {
|
|
||||||
setTimeout(() => resolve(), 1000);
|
|
||||||
});
|
|
||||||
ws.once('lost-connection', () => reject());
|
|
||||||
ws.once('connection-error', () => reject());
|
|
||||||
});
|
});
|
||||||
return to;
|
const newWorkspaceUnit = new WorkspaceUnit({
|
||||||
|
id,
|
||||||
|
name: workspaceUnit.name,
|
||||||
|
avatar: undefined,
|
||||||
|
owner: await this.getUserInfo(),
|
||||||
|
published: false,
|
||||||
|
memberCount: 1,
|
||||||
|
provider: 'affine',
|
||||||
|
syncMode: 'core',
|
||||||
|
});
|
||||||
|
|
||||||
|
const blocksuiteWorkspace = createBlocksuiteWorkspace(id);
|
||||||
|
assert(workspaceUnit.blocksuiteWorkspace);
|
||||||
|
await applyUpdate(
|
||||||
|
blocksuiteWorkspace,
|
||||||
|
encodeStateAsUpdate(workspaceUnit.blocksuiteWorkspace.doc)
|
||||||
|
);
|
||||||
|
|
||||||
|
await syncToCloud(blocksuiteWorkspace, this._apis.token.refresh);
|
||||||
|
|
||||||
|
newWorkspaceUnit.setBlocksuiteWorkspace(blocksuiteWorkspace);
|
||||||
|
|
||||||
|
this._workspaces.add(newWorkspaceUnit);
|
||||||
|
return newWorkspaceUnit;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async logout(): Promise<void> {
|
public override async logout(): Promise<void> {
|
||||||
|
|||||||
90
packages/data-center/src/provider/affine/utils.ts
Normal file
90
packages/data-center/src/provider/affine/utils.ts
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
import assert from 'assert';
|
||||||
|
import { Workspace as BlocksuiteWorkspace } from '@blocksuite/store';
|
||||||
|
import { WorkspaceUnit } from '../../workspace-unit.js';
|
||||||
|
import type { WorkspaceUnitCtorParams } from '../../workspace-unit';
|
||||||
|
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,
|
||||||
|
apis: Apis
|
||||||
|
) => {
|
||||||
|
const workspaceUnit = new WorkspaceUnit(params);
|
||||||
|
const blocksuiteWorkspace = createBlocksuiteWorkspace(workspaceUnit.id);
|
||||||
|
|
||||||
|
const updates = await apis.downloadWorkspace(
|
||||||
|
workspaceUnit.id,
|
||||||
|
params.published
|
||||||
|
);
|
||||||
|
applyUpdate(blocksuiteWorkspace, new Uint8Array(updates));
|
||||||
|
|
||||||
|
const details = await apis.getWorkspaceDetail({ id: workspaceUnit.id });
|
||||||
|
const owner = details?.owner;
|
||||||
|
|
||||||
|
workspaceUnit.setBlocksuiteWorkspace(blocksuiteWorkspace);
|
||||||
|
workspaceUnit.update({
|
||||||
|
name: blocksuiteWorkspace.meta.name,
|
||||||
|
avatar: blocksuiteWorkspace.meta.avatar,
|
||||||
|
memberCount: details?.member_count || 1,
|
||||||
|
owner: owner
|
||||||
|
? {
|
||||||
|
id: owner.id,
|
||||||
|
name: owner.name,
|
||||||
|
avatar: owner.avatar_url,
|
||||||
|
email: owner.email,
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
return workspaceUnit;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const syncToCloud = async (
|
||||||
|
blocksuiteWorkspace: BlocksuiteWorkspace,
|
||||||
|
refreshToken: string
|
||||||
|
) => {
|
||||||
|
const workspaceId = blocksuiteWorkspace.room;
|
||||||
|
assert(workspaceId, 'Blocksuite workspace without room(workspaceId).');
|
||||||
|
|
||||||
|
const wsUrl = `${window.location.protocol === 'https:' ? 'wss' : 'ws'}://${
|
||||||
|
window.location.host
|
||||||
|
}/api/sync/`;
|
||||||
|
|
||||||
|
const ws = new WebsocketProvider(
|
||||||
|
wsUrl,
|
||||||
|
workspaceId,
|
||||||
|
blocksuiteWorkspace.doc,
|
||||||
|
{
|
||||||
|
params: { token: refreshToken },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
ws.once('synced', () => {
|
||||||
|
// FIXME: we don't when send local data to cloud successfully, so hack to wait 1s.
|
||||||
|
// Server will support this by add a new api.
|
||||||
|
setTimeout(resolve, 1000);
|
||||||
|
});
|
||||||
|
ws.once('lost-connection', () => reject());
|
||||||
|
ws.once('connection-error', () => reject());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createWorkspaceUnit = async (params: WorkspaceUnitCtorParams) => {
|
||||||
|
const workspaceUnit = new WorkspaceUnit(params);
|
||||||
|
|
||||||
|
const blocksuiteWorkspace = createBlocksuiteWorkspace(workspaceUnit.id);
|
||||||
|
|
||||||
|
blocksuiteWorkspace.meta.setName(workspaceUnit.name);
|
||||||
|
if (!workspaceUnit.avatar) {
|
||||||
|
await setDefaultAvatar(blocksuiteWorkspace);
|
||||||
|
workspaceUnit.update({ avatar: blocksuiteWorkspace.meta.avatar });
|
||||||
|
}
|
||||||
|
|
||||||
|
workspaceUnit.setBlocksuiteWorkspace(blocksuiteWorkspace);
|
||||||
|
|
||||||
|
return workspaceUnit;
|
||||||
|
};
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Workspace as BlocksuiteWorkspace, uuidv4 } from '@blocksuite/store';
|
import { Workspace as BlocksuiteWorkspace } from '@blocksuite/store';
|
||||||
import { MessageCenter } from '../message';
|
import { MessageCenter } from '../message';
|
||||||
import { Logger, User } from '../types';
|
import { Logger, User } from '../types';
|
||||||
import type { WorkspaceUnitCollectionScope } from '../workspace-unit-collection';
|
import type { WorkspaceUnitCollectionScope } from '../workspace-unit-collection';
|
||||||
import type { WorkspaceUnitCtorParams } from '../workspace-unit';
|
import type { WorkspaceUnitCtorParams, WorkspaceUnit } from '../workspace-unit';
|
||||||
import { Member } from './affine/apis';
|
import { Member } from './affine/apis';
|
||||||
|
|
||||||
const defaultLogger = () => {
|
const defaultLogger = () => {
|
||||||
@@ -44,12 +44,6 @@ export class BaseProvider {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async createWorkspaceInfo(
|
|
||||||
params: CreateWorkspaceInfoParams
|
|
||||||
): Promise<WorkspaceMeta0> {
|
|
||||||
throw new Error(`provider: ${this.id} createWorkspaceInfo Not implemented`);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* auth provider
|
* auth provider
|
||||||
*/
|
*/
|
||||||
@@ -87,7 +81,7 @@ export class BaseProvider {
|
|||||||
/**
|
/**
|
||||||
* load workspaces
|
* load workspaces
|
||||||
**/
|
**/
|
||||||
public async loadWorkspaces(): Promise<WorkspaceMeta0[]> {
|
public async loadWorkspaces(): Promise<WorkspaceUnit[]> {
|
||||||
throw new Error(`provider: ${this.id} loadWorkSpace Not implemented`);
|
throw new Error(`provider: ${this.id} loadWorkSpace Not implemented`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,13 +177,18 @@ export class BaseProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* create workspace by workspace meta
|
* create workspace by workspace meta
|
||||||
* @param {WorkspaceMeta} meta
|
* @param {CreateWorkspaceInfoParams} meta
|
||||||
*/
|
*/
|
||||||
public async createWorkspace(
|
public async createWorkspace(
|
||||||
blocksuiteWorkspace: BlocksuiteWorkspace,
|
meta: CreateWorkspaceInfoParams
|
||||||
meta: WorkspaceMeta0
|
): Promise<WorkspaceUnit | undefined> {
|
||||||
): Promise<BlocksuiteWorkspace | undefined> {
|
throw new Error(`provider: ${this.id} createWorkspace not implemented`);
|
||||||
return blocksuiteWorkspace;
|
}
|
||||||
|
|
||||||
|
public async extendWorkspace(
|
||||||
|
workspaceUnit: WorkspaceUnit
|
||||||
|
): Promise<WorkspaceUnit | undefined> {
|
||||||
|
throw new Error(`provider: ${this.id} extendWorkspace not implemented`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -214,16 +213,6 @@ export class BaseProvider {
|
|||||||
return workspace;
|
return workspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* merge one workspaces to another
|
|
||||||
* @param workspace
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
public async assign(to: BlocksuiteWorkspace, from: BlocksuiteWorkspace) {
|
|
||||||
from;
|
|
||||||
return to;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get workspace members
|
* get workspace members
|
||||||
* @param {string} workspaceId
|
* @param {string} workspaceId
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
import * as idb from 'lib0/indexeddb.js';
|
import * as idb from 'lib0/indexeddb.js';
|
||||||
import { Workspace as BlocksuiteWorkspace } from '@blocksuite/store';
|
import { Workspace as BlocksuiteWorkspace } from '@blocksuite/store';
|
||||||
|
import { applyUpdate } from '../../../utils/index.js';
|
||||||
|
|
||||||
const { encodeStateAsUpdate } = BlocksuiteWorkspace.Y;
|
const { encodeStateAsUpdate, mergeUpdates } = BlocksuiteWorkspace.Y;
|
||||||
|
|
||||||
export const initStore = async (blocksuiteWorkspace: BlocksuiteWorkspace) => {
|
export const writeUpdatesToLocal = async (
|
||||||
|
blocksuiteWorkspace: BlocksuiteWorkspace
|
||||||
|
) => {
|
||||||
const workspaceId = blocksuiteWorkspace.room;
|
const workspaceId = blocksuiteWorkspace.room;
|
||||||
assert(workspaceId);
|
assert(workspaceId);
|
||||||
await idb.deleteDB(workspaceId);
|
await idb.deleteDB(workspaceId);
|
||||||
@@ -18,3 +21,21 @@ export const initStore = async (blocksuiteWorkspace: BlocksuiteWorkspace) => {
|
|||||||
await idb.addAutoKey(updatesStore, currState);
|
await idb.addAutoKey(updatesStore, currState);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const applyLocalUpdates = async (
|
||||||
|
blocksuiteWorkspace: BlocksuiteWorkspace
|
||||||
|
) => {
|
||||||
|
const workspaceId = blocksuiteWorkspace.room;
|
||||||
|
assert(workspaceId, 'Blocksuite workspace without room(workspaceId).');
|
||||||
|
const db = await idb.openDB(workspaceId, db =>
|
||||||
|
idb.createStores(db, [['updates', { autoIncrement: true }], ['custom']])
|
||||||
|
);
|
||||||
|
|
||||||
|
const [updatesStore] = idb.transact(db, ['updates']); // , 'readonly')
|
||||||
|
if (updatesStore) {
|
||||||
|
const updates = await idb.getAll(updatesStore);
|
||||||
|
const mergedUpdates = mergeUpdates(updates);
|
||||||
|
await applyUpdate(blocksuiteWorkspace, mergedUpdates);
|
||||||
|
}
|
||||||
|
return blocksuiteWorkspace;
|
||||||
|
};
|
||||||
|
|||||||
@@ -16,12 +16,10 @@ test.describe.serial('local provider', () => {
|
|||||||
let workspaceId: string | undefined;
|
let workspaceId: string | undefined;
|
||||||
|
|
||||||
test('create workspace', async () => {
|
test('create workspace', async () => {
|
||||||
const workspaceInfo = await provider.createWorkspaceInfo({
|
const workspaceUnit = await provider.createWorkspace({
|
||||||
name: workspaceName,
|
name: workspaceName,
|
||||||
});
|
});
|
||||||
workspaceId = workspaceInfo.id;
|
workspaceId = workspaceUnit?.id;
|
||||||
const blocksuiteWorkspace = createBlocksuiteWorkspace(workspaceId);
|
|
||||||
await provider.createWorkspace(blocksuiteWorkspace, workspaceInfo);
|
|
||||||
|
|
||||||
expect(workspaceMetaCollection.workspaces.length).toEqual(1);
|
expect(workspaceMetaCollection.workspaces.length).toEqual(1);
|
||||||
expect(workspaceMetaCollection.workspaces[0].name).toEqual(workspaceName);
|
expect(workspaceMetaCollection.workspaces[0].name).toEqual(workspaceName);
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ import type {
|
|||||||
import { varStorage as storage } from 'lib0/storage';
|
import { varStorage as storage } from 'lib0/storage';
|
||||||
import { Workspace as BlocksuiteWorkspace, uuidv4 } from '@blocksuite/store';
|
import { Workspace as BlocksuiteWorkspace, uuidv4 } from '@blocksuite/store';
|
||||||
import { IndexedDBProvider } from './indexeddb/indexeddb.js';
|
import { IndexedDBProvider } from './indexeddb/indexeddb.js';
|
||||||
import { initStore } from './indexeddb/utils.js';
|
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
import { setDefaultAvatar } from '../utils.js';
|
import { loadWorkspaceUnit, createWorkspaceUnit } from './utils.js';
|
||||||
|
import type { WorkspaceUnit } from '../../workspace-unit';
|
||||||
|
|
||||||
const WORKSPACE_KEY = 'workspaces';
|
const WORKSPACE_KEY = 'workspaces';
|
||||||
|
|
||||||
@@ -22,21 +22,12 @@ export class LocalProvider extends BaseProvider {
|
|||||||
super(params);
|
super(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _storeWorkspaces(workspaces: WorkspaceMeta0[]) {
|
private _storeWorkspaces(workspaceUnits: WorkspaceUnit[]) {
|
||||||
storage.setItem(
|
storage.setItem(
|
||||||
WORKSPACE_KEY,
|
WORKSPACE_KEY,
|
||||||
JSON.stringify(
|
JSON.stringify(
|
||||||
workspaces.map(w => {
|
workspaceUnits.map(w => {
|
||||||
return {
|
return w.toJSON();
|
||||||
id: w.id,
|
|
||||||
name: w.name,
|
|
||||||
avatar: w.avatar,
|
|
||||||
owner: w.owner,
|
|
||||||
published: w.published,
|
|
||||||
memberCount: w.memberCount,
|
|
||||||
provider: w.provider,
|
|
||||||
syncMode: w.syncMode,
|
|
||||||
};
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -61,20 +52,23 @@ export class LocalProvider extends BaseProvider {
|
|||||||
return workspace;
|
return workspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
override loadWorkspaces(): Promise<WorkspaceMeta0[]> {
|
override async loadWorkspaces(): Promise<WorkspaceUnit[]> {
|
||||||
const workspaceStr = storage.getItem(WORKSPACE_KEY);
|
const workspaceStr = storage.getItem(WORKSPACE_KEY);
|
||||||
let workspaces: WorkspaceMeta0[] = [];
|
|
||||||
if (workspaceStr) {
|
if (workspaceStr) {
|
||||||
try {
|
try {
|
||||||
workspaces = JSON.parse(workspaceStr) as WorkspaceMeta0[];
|
const workspaceMetas = JSON.parse(workspaceStr) as WorkspaceMeta0[];
|
||||||
workspaces.forEach(workspace => {
|
const workspaceUnits = await Promise.all(
|
||||||
this._workspaces.add(workspace);
|
workspaceMetas.map(meta => {
|
||||||
});
|
return loadWorkspaceUnit(meta);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
this._workspaces.add(workspaceUnits);
|
||||||
|
return workspaceUnits;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this._logger(`Failed to parse workspaces from storage`);
|
this._logger(`Failed to parse workspaces from storage`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.resolve(workspaces);
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async deleteWorkspace(id: string): Promise<void> {
|
public override async deleteWorkspace(id: string): Promise<void> {
|
||||||
@@ -96,10 +90,10 @@ export class LocalProvider extends BaseProvider {
|
|||||||
this._storeWorkspaces(this._workspaces.list());
|
this._storeWorkspaces(this._workspaces.list());
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async createWorkspaceInfo(
|
public override async createWorkspace(
|
||||||
meta: CreateWorkspaceInfoParams
|
meta: CreateWorkspaceInfoParams
|
||||||
): Promise<WorkspaceMeta0> {
|
): Promise<WorkspaceUnit | undefined> {
|
||||||
const workspaceInfo: WorkspaceMeta0 = {
|
const workspaceUnit = await createWorkspaceUnit({
|
||||||
name: meta.name,
|
name: meta.name,
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
published: false,
|
published: false,
|
||||||
@@ -108,35 +102,10 @@ export class LocalProvider extends BaseProvider {
|
|||||||
syncMode: 'core',
|
syncMode: 'core',
|
||||||
memberCount: 1,
|
memberCount: 1,
|
||||||
provider: 'local',
|
provider: 'local',
|
||||||
};
|
});
|
||||||
return Promise.resolve(workspaceInfo);
|
this._workspaces.add(workspaceUnit);
|
||||||
}
|
|
||||||
|
|
||||||
public override async createWorkspace(
|
|
||||||
blocksuiteWorkspace: BlocksuiteWorkspace,
|
|
||||||
meta: WorkspaceMeta0
|
|
||||||
): Promise<BlocksuiteWorkspace | undefined> {
|
|
||||||
const workspaceId = blocksuiteWorkspace.room;
|
|
||||||
assert(workspaceId, 'Blocksuite Workspace without room(workspaceId).');
|
|
||||||
this._logger('Creating affine workspace');
|
|
||||||
|
|
||||||
const workspaceInfo: WorkspaceMeta0 = {
|
|
||||||
...meta,
|
|
||||||
};
|
|
||||||
|
|
||||||
blocksuiteWorkspace.meta.setName(meta.name);
|
|
||||||
|
|
||||||
if (!meta.avatar) {
|
|
||||||
await setDefaultAvatar(blocksuiteWorkspace);
|
|
||||||
workspaceInfo.avatar = blocksuiteWorkspace.meta.avatar;
|
|
||||||
}
|
|
||||||
|
|
||||||
await initStore(blocksuiteWorkspace);
|
|
||||||
|
|
||||||
this._workspaces.add(workspaceInfo);
|
|
||||||
this._storeWorkspaces(this._workspaces.list());
|
this._storeWorkspaces(this._workspaces.list());
|
||||||
|
return workspaceUnit;
|
||||||
return blocksuiteWorkspace;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async clear(): Promise<void> {
|
public override async clear(): Promise<void> {
|
||||||
|
|||||||
34
packages/data-center/src/provider/local/utils.ts
Normal file
34
packages/data-center/src/provider/local/utils.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { WorkspaceUnit } from '../../workspace-unit.js';
|
||||||
|
import type { WorkspaceUnitCtorParams } from '../../workspace-unit';
|
||||||
|
import { createBlocksuiteWorkspace } from '../../utils/index.js';
|
||||||
|
import { applyLocalUpdates, writeUpdatesToLocal } from './indexeddb/utils.js';
|
||||||
|
import { setDefaultAvatar } from '../utils.js';
|
||||||
|
|
||||||
|
export const loadWorkspaceUnit = async (params: WorkspaceUnitCtorParams) => {
|
||||||
|
const workspaceUnit = new WorkspaceUnit(params);
|
||||||
|
|
||||||
|
const blocksuiteWorkspace = createBlocksuiteWorkspace(workspaceUnit.id);
|
||||||
|
|
||||||
|
await applyLocalUpdates(blocksuiteWorkspace);
|
||||||
|
|
||||||
|
workspaceUnit.setBlocksuiteWorkspace(blocksuiteWorkspace);
|
||||||
|
|
||||||
|
return workspaceUnit;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createWorkspaceUnit = async (params: WorkspaceUnitCtorParams) => {
|
||||||
|
const workspaceUnit = new WorkspaceUnit(params);
|
||||||
|
|
||||||
|
const blocksuiteWorkspace = createBlocksuiteWorkspace(workspaceUnit.id);
|
||||||
|
blocksuiteWorkspace.meta.setName(workspaceUnit.name);
|
||||||
|
if (!workspaceUnit.avatar) {
|
||||||
|
await setDefaultAvatar(blocksuiteWorkspace);
|
||||||
|
workspaceUnit.update({ avatar: blocksuiteWorkspace.meta.avatar });
|
||||||
|
}
|
||||||
|
|
||||||
|
await writeUpdatesToLocal(blocksuiteWorkspace);
|
||||||
|
|
||||||
|
workspaceUnit.setBlocksuiteWorkspace(blocksuiteWorkspace);
|
||||||
|
|
||||||
|
return workspaceUnit;
|
||||||
|
};
|
||||||
@@ -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));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from '@playwright/test';
|
||||||
import { WorkspaceUnitCollection } from './workspace-unit-collection.js';
|
import { WorkspaceUnitCollection } from './workspace-unit-collection.js';
|
||||||
import type { WorkspaceUnitCollectionChangeEvent } from './workspace-unit-collection';
|
import type { WorkspaceUnitCollectionChangeEvent } from './workspace-unit-collection';
|
||||||
|
import { WorkspaceUnit } from './workspace-unit.js';
|
||||||
|
|
||||||
test.describe.serial('workspace meta collection observable', () => {
|
test.describe.serial('workspace meta collection observable', () => {
|
||||||
const workspaceUnitCollection = new WorkspaceUnitCollection();
|
const workspaceUnitCollection = new WorkspaceUnitCollection();
|
||||||
@@ -14,13 +15,15 @@ test.describe.serial('workspace meta collection observable', () => {
|
|||||||
expect(event.added?.[0]?.id).toEqual('123');
|
expect(event.added?.[0]?.id).toEqual('123');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
scope.add({
|
const workspaceUnit = new WorkspaceUnit({
|
||||||
id: '123',
|
id: '123',
|
||||||
name: 'test',
|
name: 'test',
|
||||||
|
avatar: undefined,
|
||||||
memberCount: 1,
|
memberCount: 1,
|
||||||
provider: '',
|
provider: '',
|
||||||
syncMode: 'core',
|
syncMode: 'core',
|
||||||
});
|
});
|
||||||
|
scope.add(workspaceUnit);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('list workspace', () => {
|
test('list workspace', () => {
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
import { Observable } from 'lib0/observable';
|
import { Observable } from 'lib0/observable';
|
||||||
import { WorkspaceUnit } from './workspace-unit.js';
|
|
||||||
import type {
|
import type {
|
||||||
WorkspaceUnitCtorParams,
|
WorkspaceUnit,
|
||||||
UpdateWorkspaceUnitParams,
|
UpdateWorkspaceUnitParams,
|
||||||
} from './workspace-unit';
|
} from './workspace-unit';
|
||||||
|
|
||||||
export interface WorkspaceUnitCollectionScope {
|
export interface WorkspaceUnitCollectionScope {
|
||||||
get: (workspaceId: string) => WorkspaceUnit | undefined;
|
get: (workspaceId: string) => WorkspaceUnit | undefined;
|
||||||
list: () => WorkspaceUnit[];
|
list: () => WorkspaceUnit[];
|
||||||
add: (workspace: WorkspaceUnitCtorParams) => void;
|
add: (workspace: WorkspaceUnit | WorkspaceUnit[]) => void;
|
||||||
remove: (workspaceId: string) => boolean;
|
remove: (workspaceId: string) => boolean;
|
||||||
clear: () => void;
|
clear: () => void;
|
||||||
update: (
|
update: (
|
||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
workspaceMeta: UpdateWorkspaceUnitParams
|
workspaceUnit: UpdateWorkspaceUnitParams
|
||||||
) => void;
|
) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,20 +58,23 @@ export class WorkspaceUnitCollection {
|
|||||||
return this._workspaceUnitMap.get(workspaceId);
|
return this._workspaceUnitMap.get(workspaceId);
|
||||||
};
|
};
|
||||||
|
|
||||||
const add = (workspace: WorkspaceUnitCtorParams) => {
|
const add = (workspaceUnit: WorkspaceUnit | WorkspaceUnit[]) => {
|
||||||
if (this._workspaceUnitMap.has(workspace.id)) {
|
const workspaceUnits = Array.isArray(workspaceUnit)
|
||||||
// FIXME: multiple add same workspace
|
? workspaceUnit
|
||||||
return;
|
: [workspaceUnit];
|
||||||
}
|
|
||||||
|
|
||||||
const workspaceUnit = new WorkspaceUnit(workspace);
|
workspaceUnits.forEach(workspaceUnit => {
|
||||||
this._workspaceUnitMap.set(workspace.id.toString(), workspaceUnit);
|
if (this._workspaceUnitMap.has(workspaceUnit.id)) {
|
||||||
|
// FIXME: multiple add same workspace
|
||||||
scopedWorkspaceIds.add(workspace.id);
|
return;
|
||||||
|
}
|
||||||
|
this._workspaceUnitMap.set(workspaceUnit.id, workspaceUnit);
|
||||||
|
scopedWorkspaceIds.add(workspaceUnit.id);
|
||||||
|
});
|
||||||
|
|
||||||
this._events.emit('change', [
|
this._events.emit('change', [
|
||||||
{
|
{
|
||||||
added: [workspaceUnit],
|
added: workspaceUnits,
|
||||||
} as WorkspaceUnitCollectionChangeEvent,
|
} as WorkspaceUnitCollectionChangeEvent,
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
@@ -107,10 +109,7 @@ export class WorkspaceUnitCollection {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const update = (
|
const update = (workspaceId: string, meta: UpdateWorkspaceUnitParams) => {
|
||||||
workspaceId: string,
|
|
||||||
workspaceMeta: UpdateWorkspaceUnitParams
|
|
||||||
) => {
|
|
||||||
if (!scopedWorkspaceIds.has(workspaceId)) {
|
if (!scopedWorkspaceIds.has(workspaceId)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -120,7 +119,7 @@ export class WorkspaceUnitCollection {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
workspaceUnit.update(workspaceMeta);
|
workspaceUnit.update(meta);
|
||||||
|
|
||||||
this._events.emit('change', [
|
this._events.emit('change', [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -37,6 +37,16 @@ export class WorkspaceUnit {
|
|||||||
this.update(params);
|
this.update(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isPublish() {
|
||||||
|
console.error('Suggest changing to published');
|
||||||
|
return this.published;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isLocal() {
|
||||||
|
console.error('Suggest changing to syncMode');
|
||||||
|
return this.syncMode === 'all';
|
||||||
|
}
|
||||||
|
|
||||||
get blocksuiteWorkspace() {
|
get blocksuiteWorkspace() {
|
||||||
return this._blocksuiteWorkspace;
|
return this._blocksuiteWorkspace;
|
||||||
}
|
}
|
||||||
@@ -52,13 +62,16 @@ export class WorkspaceUnit {
|
|||||||
Object.assign(this, params);
|
Object.assign(this, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
get isPublish() {
|
toJSON(): Omit<WorkspaceUnitCtorParams, 'blocksuiteWorkspace'> {
|
||||||
console.error('Suggest changing to published');
|
return {
|
||||||
return this.published;
|
id: this.id,
|
||||||
}
|
name: this.name,
|
||||||
|
avatar: this.avatar,
|
||||||
get isLocal() {
|
owner: this.owner,
|
||||||
console.error('Suggest changing to syncMode');
|
published: this.published,
|
||||||
return this.syncMode === 'all';
|
memberCount: this.memberCount,
|
||||||
|
provider: this.provider,
|
||||||
|
syncMode: this.syncMode,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user