refactor: support suspense mode in workspaces (#1304)

This commit is contained in:
Himself65
2023-03-04 20:11:15 -06:00
committed by GitHub
parent dd6bee68cb
commit 9a199eb9a1
27 changed files with 713 additions and 652 deletions
+46 -91
View File
@@ -1,4 +1,4 @@
import { assertEquals } from '@blocksuite/store';
import { createJSONStorage } from 'jotai/utils';
import React from 'react';
import { preload } from 'swr';
import { z } from 'zod';
@@ -19,6 +19,7 @@ import { createEmptyBlockSuiteWorkspace } from '../../utils';
import { WorkspacePlugin } from '..';
import { fetcher, QueryKey } from './fetcher';
const storage = createJSONStorage(() => localStorage);
const kAffineLocal = 'affine-local-storage-v2';
const schema = z.object({
id: z.string(),
@@ -31,33 +32,48 @@ const schema = z.object({
export const AffinePlugin: WorkspacePlugin<RemWorkspaceFlavour.AFFINE> = {
flavour: RemWorkspaceFlavour.AFFINE,
loadPriority: LoadPriority.HIGH,
createWorkspace: async (blockSuiteWorkspace: BlockSuiteWorkspace) => {
const binary = BlockSuiteWorkspace.Y.encodeStateAsUpdate(
blockSuiteWorkspace.doc
);
const { id } = await apis.createWorkspace(new Blob([binary.buffer]));
return id;
},
deleteWorkspace: async workspace => {
await apis.deleteWorkspace({
id: workspace.id,
});
workspace.providers.forEach(p => p.cleanup());
},
prefetchData: async dataCenter => {
if (localStorage.getItem(kAffineLocal)) {
const localData = JSON.parse(localStorage.getItem(kAffineLocal) || '[]');
if (Array.isArray(localData)) {
const workspacesDump = localData
.map((item: any) => {
const result = schema.safeParse(item);
if (result.success) {
return result.data;
}
return null;
})
.filter(Boolean) as z.infer<typeof schema>[];
const workspaces = workspacesDump.map(workspace => {
CRUD: {
create: async blockSuiteWorkspace => {
const binary = BlockSuiteWorkspace.Y.encodeStateAsUpdate(
blockSuiteWorkspace.doc
);
const { id } = await apis.createWorkspace(new Blob([binary.buffer]));
return id;
},
delete: async workspace => {
await apis.deleteWorkspace({
id: workspace.id,
});
},
get: async workspaceId => {
const workspaces: AffineWorkspace[] = await preload(
QueryKey.getWorkspaces,
fetcher
);
const workspace = workspaces.find(
workspace => workspace.id === workspaceId
);
const dump = workspaces.map(workspace => {
return {
id: workspace.id,
type: workspace.type,
public: workspace.public,
permission: workspace.permission,
create_at: workspace.create_at,
} satisfies z.infer<typeof schema>;
});
storage.setItem(kAffineLocal, dump);
if (!workspace) {
return null;
}
return workspace;
},
list: async () => {
// fixme: refactor auth check
if (!apis.auth.isLogin) return [];
return await apis.getWorkspaces().then(workspaces => {
return workspaces.map(workspace => {
const blockSuiteWorkspace = createEmptyBlockSuiteWorkspace(
workspace.id,
(k: string) =>
@@ -66,75 +82,14 @@ export const AffinePlugin: WorkspacePlugin<RemWorkspaceFlavour.AFFINE> = {
);
const affineWorkspace: AffineWorkspace = {
...workspace,
flavour: RemWorkspaceFlavour.AFFINE,
blockSuiteWorkspace,
providers: [...createAffineProviders(blockSuiteWorkspace)],
flavour: RemWorkspaceFlavour.AFFINE,
};
return affineWorkspace;
});
// fixme: refactor to a function
workspaces.forEach(workspace => {
const exist = dataCenter.workspaces.findIndex(
ws => ws.id === workspace.id
);
if (exist !== -1) {
dataCenter.workspaces.splice(exist, 1, workspace);
dataCenter.workspaces = [...dataCenter.workspaces];
} else {
dataCenter.workspaces = [...dataCenter.workspaces, workspace];
}
});
dataCenter.callbacks.forEach(cb => cb());
} else {
localStorage.removeItem(kAffineLocal);
}
}
const promise: Promise<AffineWorkspace[]> = preload(
QueryKey.getWorkspaces,
fetcher
);
return promise
.then(async workspaces => {
const promises = workspaces.map(workspace => {
assertEquals(workspace.flavour, RemWorkspaceFlavour.AFFINE);
return workspace;
});
return Promise.all(promises)
.then(workspaces => {
workspaces.forEach(workspace => {
if (workspace === null) {
return;
}
const exist = dataCenter.workspaces.findIndex(
ws => ws.id === workspace.id
);
if (exist !== -1) {
dataCenter.workspaces.splice(exist, 1, workspace);
dataCenter.workspaces = [...dataCenter.workspaces];
} else {
dataCenter.workspaces = [...dataCenter.workspaces, workspace];
}
});
return workspaces;
})
.then(ws => {
const workspaces = ws.filter(Boolean) as AffineWorkspace[];
const dump = workspaces.map(workspace => {
return {
id: workspace.id,
type: workspace.type,
public: workspace.public,
permission: workspace.permission,
create_at: workspace.create_at,
} satisfies z.infer<typeof schema>;
});
localStorage.setItem(kAffineLocal, JSON.stringify(dump));
});
})
.catch(error => {
console.error(error);
});
},
},
PageDetail: ({ currentWorkspace, currentPageId }) => {
const page = currentWorkspace.blockSuiteWorkspace.getPage(currentPageId);