mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-14 21:27:20 +00:00
refactor: workspace loading logic (#1966)
This commit is contained in:
@@ -1,40 +1,68 @@
|
||||
import { DebugLogger } from '@affine/debug';
|
||||
import { atomWithSyncStorage } from '@affine/jotai';
|
||||
import { jotaiWorkspacesAtom } from '@affine/workspace/atom';
|
||||
import type { EditorContainer } from '@blocksuite/editor';
|
||||
import type { RootWorkspaceMetadata } from '@affine/workspace/atom';
|
||||
import {
|
||||
rootCurrentEditorAtom,
|
||||
rootCurrentPageIdAtom,
|
||||
rootCurrentWorkspaceIdAtom,
|
||||
rootWorkspacesMetadataAtom,
|
||||
} from '@affine/workspace/atom';
|
||||
import type { Page } from '@blocksuite/store';
|
||||
import { assertExists } from '@blocksuite/store';
|
||||
import { atom } from 'jotai';
|
||||
|
||||
import { WorkspacePlugins } from '../plugins';
|
||||
import type { AllWorkspace } from '../shared';
|
||||
|
||||
const logger = new DebugLogger('web:atoms');
|
||||
|
||||
// workspace necessary atoms
|
||||
export const currentWorkspaceIdAtom = atom<string | null>(null);
|
||||
export const currentPageIdAtom = atom<string | null>(null);
|
||||
export const currentEditorAtom = atom<Readonly<EditorContainer> | null>(null);
|
||||
/**
|
||||
* @deprecated Use `rootCurrentWorkspaceIdAtom` directly instead.
|
||||
*/
|
||||
export const currentWorkspaceIdAtom = rootCurrentWorkspaceIdAtom;
|
||||
|
||||
// todo(himself65): move this to the workspace package
|
||||
rootWorkspacesMetadataAtom.onMount = setAtom => {
|
||||
function createFirst(): RootWorkspaceMetadata[] {
|
||||
const Plugins = Object.values(WorkspacePlugins).sort(
|
||||
(a, b) => a.loadPriority - b.loadPriority
|
||||
);
|
||||
|
||||
return Plugins.flatMap(Plugin => {
|
||||
return Plugin.Events['app:init']?.().map(
|
||||
id =>
|
||||
({
|
||||
id,
|
||||
flavour: Plugin.flavour,
|
||||
} satisfies RootWorkspaceMetadata)
|
||||
);
|
||||
}).filter((ids): ids is RootWorkspaceMetadata => !!ids);
|
||||
}
|
||||
|
||||
setAtom(metadata => {
|
||||
if (metadata.length === 0) {
|
||||
const newMetadata = createFirst();
|
||||
logger.info('create first workspace', newMetadata);
|
||||
return newMetadata;
|
||||
}
|
||||
return metadata;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated Use `rootCurrentPageIdAtom` directly instead.
|
||||
*/
|
||||
export const currentPageIdAtom = rootCurrentPageIdAtom;
|
||||
/**
|
||||
* @deprecated Use `rootCurrentEditorAtom` directly instead.
|
||||
*/
|
||||
export const currentEditorAtom = rootCurrentEditorAtom;
|
||||
|
||||
// modal atoms
|
||||
export const openWorkspacesModalAtom = atom(false);
|
||||
export const openCreateWorkspaceModalAtom = atom(false);
|
||||
export const openQuickSearchModalAtom = atom(false);
|
||||
|
||||
export const workspacesAtom = atom<Promise<AllWorkspace[]>>(async get => {
|
||||
const flavours: string[] = Object.values(WorkspacePlugins).map(
|
||||
plugin => plugin.flavour
|
||||
);
|
||||
const jotaiWorkspaces = get(jotaiWorkspacesAtom).filter(workspace =>
|
||||
flavours.includes(workspace.flavour)
|
||||
);
|
||||
const workspaces = await Promise.all(
|
||||
jotaiWorkspaces.map(workspace => {
|
||||
const plugin =
|
||||
WorkspacePlugins[workspace.flavour as keyof typeof WorkspacePlugins];
|
||||
assertExists(plugin);
|
||||
const { CRUD } = plugin;
|
||||
return CRUD.get(workspace.id);
|
||||
})
|
||||
);
|
||||
return workspaces.filter(workspace => workspace !== null) as AllWorkspace[];
|
||||
});
|
||||
export { workspacesAtom } from './root';
|
||||
|
||||
type View = { id: string; mode: 'page' | 'edgeless' };
|
||||
|
||||
|
||||
78
apps/web/src/atoms/root.ts
Normal file
78
apps/web/src/atoms/root.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
//#region async atoms that to load the real workspace data
|
||||
import { DebugLogger } from '@affine/debug';
|
||||
import {
|
||||
rootCurrentWorkspaceIdAtom,
|
||||
rootWorkspacesMetadataAtom,
|
||||
} from '@affine/workspace/atom';
|
||||
import { assertExists } from '@blocksuite/store';
|
||||
import { atom } from 'jotai';
|
||||
|
||||
import { WorkspacePlugins } from '../plugins';
|
||||
import type { AllWorkspace } from '../shared';
|
||||
|
||||
const logger = new DebugLogger('web:atoms:root');
|
||||
|
||||
/**
|
||||
* Fetch all workspaces from the Plugin CRUD
|
||||
*/
|
||||
export const workspacesAtom = atom<Promise<AllWorkspace[]>>(async get => {
|
||||
const flavours: string[] = Object.values(WorkspacePlugins).map(
|
||||
plugin => plugin.flavour
|
||||
);
|
||||
const jotaiWorkspaces = get(rootWorkspacesMetadataAtom).filter(workspace =>
|
||||
flavours.includes(workspace.flavour)
|
||||
);
|
||||
const workspaces = await Promise.all(
|
||||
jotaiWorkspaces.map(workspace => {
|
||||
const plugin =
|
||||
WorkspacePlugins[workspace.flavour as keyof typeof WorkspacePlugins];
|
||||
assertExists(plugin);
|
||||
const { CRUD } = plugin;
|
||||
return CRUD.get(workspace.id);
|
||||
})
|
||||
);
|
||||
logger.info('workspaces', workspaces);
|
||||
workspaces.forEach(workspace => {
|
||||
if (workspace === null) {
|
||||
console.warn(
|
||||
'workspace is null. this should not happen. If you see this error, please report it to the developer.'
|
||||
);
|
||||
}
|
||||
});
|
||||
return workspaces.filter(workspace => workspace !== null) as AllWorkspace[];
|
||||
});
|
||||
|
||||
/**
|
||||
* This will throw an error if the workspace is not found,
|
||||
* should not be used on the root component,
|
||||
* use `rootCurrentWorkspaceIdAtom` instead
|
||||
*/
|
||||
export const rootCurrentWorkspaceAtom = atom<Promise<AllWorkspace>>(
|
||||
async get => {
|
||||
const metadata = get(rootWorkspacesMetadataAtom);
|
||||
const targetId = get(rootCurrentWorkspaceIdAtom);
|
||||
if (targetId === null) {
|
||||
throw new Error(
|
||||
'current workspace id is null. this should not happen. If you see this error, please report it to the developer.'
|
||||
);
|
||||
}
|
||||
const targetWorkspace = metadata.find(meta => meta.id === targetId);
|
||||
if (!targetWorkspace) {
|
||||
throw new Error(`cannot find the workspace with id ${targetId}.`);
|
||||
}
|
||||
const workspace = await WorkspacePlugins[targetWorkspace.flavour].CRUD.get(
|
||||
targetWorkspace.id
|
||||
);
|
||||
if (!workspace) {
|
||||
throw new Error(
|
||||
`cannot find the workspace with id ${targetId} in the plugin ${targetWorkspace.flavour}.`
|
||||
);
|
||||
}
|
||||
return workspace;
|
||||
}
|
||||
);
|
||||
|
||||
// Do not add `rootCurrentWorkspacePageAtom`, this is not needed.
|
||||
// It can be derived from `rootCurrentWorkspaceAtom` and `rootCurrentPageIdAtom`
|
||||
|
||||
//#endregion
|
||||
Reference in New Issue
Block a user