mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-14 21:27:20 +00:00
refactor(infra): migrate to new infra (#5565)
This commit is contained in:
@@ -3,101 +3,71 @@
|
||||
*/
|
||||
import 'fake-indexeddb/auto';
|
||||
|
||||
import {
|
||||
currentWorkspaceAtom,
|
||||
WorkspacePropertiesAdapter,
|
||||
} from '@affine/core/modules/workspace';
|
||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||
import type { Workspace } from '@affine/workspace/workspace';
|
||||
import { __unstableSchemas, AffineSchemas } from '@blocksuite/blocks/models';
|
||||
import { assertExists } from '@blocksuite/global/utils';
|
||||
import { type Page, Workspace as BlockSuiteWorkspace } from '@blocksuite/store';
|
||||
import { Schema } from '@blocksuite/store';
|
||||
import { WorkspacePropertiesAdapter } from '@affine/core/modules/workspace';
|
||||
import { render } from '@testing-library/react';
|
||||
import { Workspace } from '@toeverything/infra';
|
||||
import { ServiceProviderContext, useService } from '@toeverything/infra/di';
|
||||
import { createStore, Provider } from 'jotai';
|
||||
import { Suspense } from 'react';
|
||||
import { describe, expect, test, vi } from 'vitest';
|
||||
import { beforeEach } from 'vitest';
|
||||
|
||||
import { configureTestingEnvironment } from '../../testing';
|
||||
import { useBlockSuiteWorkspacePageTitle } from '../use-block-suite-workspace-page-title';
|
||||
|
||||
let blockSuiteWorkspace: BlockSuiteWorkspace;
|
||||
const store = createStore();
|
||||
|
||||
const schema = new Schema();
|
||||
schema.register(AffineSchemas).register(__unstableSchemas);
|
||||
|
||||
const Component = () => {
|
||||
const title = useBlockSuiteWorkspacePageTitle(blockSuiteWorkspace, 'page0');
|
||||
const workspace = useService(Workspace);
|
||||
const title = useBlockSuiteWorkspacePageTitle(
|
||||
workspace.blockSuiteWorkspace,
|
||||
'page0'
|
||||
);
|
||||
return <div>title: {title}</div>;
|
||||
};
|
||||
|
||||
// todo: this module has some side-effects that will break the tests
|
||||
vi.mock('@affine/workspace-impl', () => ({
|
||||
default: {},
|
||||
}));
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.useFakeTimers({ toFake: ['requestIdleCallback'] });
|
||||
|
||||
blockSuiteWorkspace = new BlockSuiteWorkspace({ id: 'test', schema });
|
||||
|
||||
const workspace = {
|
||||
blockSuiteWorkspace,
|
||||
flavour: WorkspaceFlavour.LOCAL,
|
||||
} as Workspace;
|
||||
|
||||
store.set(currentWorkspaceAtom, workspace);
|
||||
|
||||
blockSuiteWorkspace = workspace.blockSuiteWorkspace;
|
||||
|
||||
blockSuiteWorkspace.doc.emit('sync', []);
|
||||
|
||||
const initPage = async (page: Page) => {
|
||||
await page.waitForLoaded();
|
||||
expect(page).not.toBeNull();
|
||||
assertExists(page);
|
||||
const pageBlockId = page.addBlock('affine:page', {
|
||||
title: new page.Text(''),
|
||||
});
|
||||
const frameId = page.addBlock('affine:note', {}, pageBlockId);
|
||||
page.addBlock('affine:paragraph', {}, frameId);
|
||||
};
|
||||
await initPage(blockSuiteWorkspace.createPage({ id: 'page0' }));
|
||||
await initPage(blockSuiteWorkspace.createPage({ id: 'page1' }));
|
||||
await initPage(blockSuiteWorkspace.createPage({ id: 'page2' }));
|
||||
});
|
||||
|
||||
describe('useBlockSuiteWorkspacePageTitle', () => {
|
||||
test('basic', async () => {
|
||||
const { workspace, page } = await configureTestingEnvironment();
|
||||
const { findByText, rerender } = render(
|
||||
<Provider store={store}>
|
||||
<Suspense fallback="loading">
|
||||
<Component />
|
||||
</Suspense>
|
||||
</Provider>
|
||||
<ServiceProviderContext.Provider value={page.services}>
|
||||
<Provider store={store}>
|
||||
<Suspense fallback="loading">
|
||||
<Component />
|
||||
</Suspense>
|
||||
</Provider>
|
||||
</ServiceProviderContext.Provider>
|
||||
);
|
||||
expect(await findByText('title: Untitled')).toBeDefined();
|
||||
blockSuiteWorkspace.setPageMeta('page0', { title: '1' });
|
||||
workspace.blockSuiteWorkspace.setPageMeta(page.id, { title: '1' });
|
||||
rerender(
|
||||
<Provider store={store}>
|
||||
<Suspense fallback="loading">
|
||||
<Component />
|
||||
</Suspense>
|
||||
</Provider>
|
||||
<ServiceProviderContext.Provider value={page.services}>
|
||||
<Provider store={store}>
|
||||
<Suspense fallback="loading">
|
||||
<Component />
|
||||
</Suspense>
|
||||
</Provider>
|
||||
</ServiceProviderContext.Provider>
|
||||
);
|
||||
expect(await findByText('title: 1')).toBeDefined();
|
||||
});
|
||||
|
||||
test('journal', async () => {
|
||||
const adapter = new WorkspacePropertiesAdapter(blockSuiteWorkspace);
|
||||
adapter.setJournalPageDateString('page0', '2021-01-01');
|
||||
const { workspace, page } = await configureTestingEnvironment();
|
||||
const adapter = workspace.services.get(WorkspacePropertiesAdapter);
|
||||
adapter.setJournalPageDateString(page.id, '2021-01-01');
|
||||
const { findByText } = render(
|
||||
<Provider store={store}>
|
||||
<Suspense fallback="loading">
|
||||
<Component />
|
||||
</Suspense>
|
||||
</Provider>
|
||||
<ServiceProviderContext.Provider value={page.services}>
|
||||
<Provider store={store}>
|
||||
<Suspense fallback="loading">
|
||||
<Component />
|
||||
</Suspense>
|
||||
</Provider>
|
||||
</ServiceProviderContext.Provider>
|
||||
);
|
||||
expect(await findByText('title: Jan 1, 2021')).toBeDefined();
|
||||
});
|
||||
|
||||
@@ -4,17 +4,17 @@ import {
|
||||
FavoriteTag,
|
||||
} from '@affine/core/components/page-list';
|
||||
import { useBlockSuitePageMeta } from '@affine/core/hooks/use-block-suite-page-meta';
|
||||
import { waitForCurrentWorkspaceAtom } from '@affine/core/modules/workspace';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import type { PageMeta } from '@blocksuite/store';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import { Workspace } from '@toeverything/infra';
|
||||
import { useService } from '@toeverything/infra/di';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
import { usePageHelper } from '../../components/blocksuite/block-suite-page-list/utils';
|
||||
import { useBlockSuiteMetaHelper } from './use-block-suite-meta-helper';
|
||||
|
||||
export const useAllPageListConfig = () => {
|
||||
const currentWorkspace = useAtomValue(waitForCurrentWorkspaceAtom);
|
||||
const currentWorkspace = useService(Workspace);
|
||||
const workspace = currentWorkspace.blockSuiteWorkspace;
|
||||
const pageMetas = useBlockSuitePageMeta(workspace);
|
||||
const { isPreferredEdgeless } = usePageHelper(workspace);
|
||||
|
||||
@@ -4,6 +4,8 @@ import {
|
||||
usePageMetaHelper,
|
||||
} from '@affine/core/hooks/use-block-suite-page-meta';
|
||||
import { useBlockSuiteWorkspaceHelper } from '@affine/core/hooks/use-block-suite-workspace-helper';
|
||||
import { CollectionService } from '@affine/core/modules/collection';
|
||||
import { useService } from '@toeverything/infra';
|
||||
import { useAtomValue, useSetAtom } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
import { applyUpdate, encodeStateAsUpdate } from 'yjs';
|
||||
@@ -11,7 +13,6 @@ import { applyUpdate, encodeStateAsUpdate } from 'yjs';
|
||||
import { setPageModeAtom } from '../../atoms';
|
||||
import { currentModeAtom } from '../../atoms/mode';
|
||||
import type { BlockSuiteWorkspace } from '../../shared';
|
||||
import { getWorkspaceSetting } from '../../utils/workspace-setting';
|
||||
import { useNavigateHelper } from '../use-navigate-helper';
|
||||
import { useReferenceLinkHelper } from './use-reference-link-helper';
|
||||
|
||||
@@ -26,6 +27,7 @@ export function useBlockSuiteMetaHelper(
|
||||
const currentMode = useAtomValue(currentModeAtom);
|
||||
const { createPage } = useBlockSuiteWorkspaceHelper(blockSuiteWorkspace);
|
||||
const { openPage } = useNavigateHelper();
|
||||
const collectionService = useService(CollectionService);
|
||||
|
||||
const switchToPageMode = useCallback(
|
||||
(pageId: string) => {
|
||||
@@ -89,9 +91,9 @@ export function useBlockSuiteMetaHelper(
|
||||
trashRelate: isRoot ? parentMeta?.id : undefined,
|
||||
});
|
||||
setPageReadonly(pageId, true);
|
||||
getWorkspaceSetting(blockSuiteWorkspace).deletePages([pageId]);
|
||||
collectionService.deletePagesFromCollections([pageId]);
|
||||
},
|
||||
[blockSuiteWorkspace, getPageMeta, metas, setPageMeta, setPageReadonly]
|
||||
[collectionService, getPageMeta, metas, setPageMeta, setPageReadonly]
|
||||
);
|
||||
|
||||
const restoreFromTrash = useCallback(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||
import { getIsOwnerQuery } from '@affine/graphql';
|
||||
import type { WorkspaceMetadata } from '@affine/workspace/metadata';
|
||||
import type { WorkspaceMetadata } from '@toeverything/infra';
|
||||
|
||||
import { useQueryImmutable } from '../use-query';
|
||||
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import { toast } from '@affine/component';
|
||||
import { usePageMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta';
|
||||
import { waitForCurrentWorkspaceAtom } from '@affine/core/modules/workspace';
|
||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { assertExists } from '@blocksuite/global/utils';
|
||||
import { EdgelessIcon, HistoryIcon, PageIcon } from '@blocksuite/icons';
|
||||
import { Workspace } from '@toeverything/infra';
|
||||
import {
|
||||
PreconditionStrategy,
|
||||
registerAffineCommand,
|
||||
} from '@toeverything/infra/command';
|
||||
import { useAtomValue, useSetAtom } from 'jotai';
|
||||
import { useService } from '@toeverything/infra/di';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
|
||||
import { pageHistoryModalAtom } from '../../atoms/page-history';
|
||||
@@ -22,7 +23,7 @@ export function useRegisterBlocksuiteEditorCommands(
|
||||
mode: 'page' | 'edgeless'
|
||||
) {
|
||||
const t = useAFFiNEI18N();
|
||||
const workspace = useAtomValue(waitForCurrentWorkspaceAtom);
|
||||
const workspace = useService(Workspace);
|
||||
const blockSuiteWorkspace = workspace.blockSuiteWorkspace;
|
||||
const { getPageMeta } = usePageMetaHelper(blockSuiteWorkspace);
|
||||
const currentPage = blockSuiteWorkspace.getPage(pageId);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { toast } from '@affine/component';
|
||||
import type { DraggableTitleCellData } from '@affine/core/components/page-list';
|
||||
import { usePageMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta';
|
||||
import { waitForCurrentWorkspaceAtom } from '@affine/core/modules/workspace';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import type { DragEndEvent, UniqueIdentifier } from '@dnd-kit/core';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import { Workspace } from '@toeverything/infra';
|
||||
import { useService } from '@toeverything/infra/di';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useBlockSuiteMetaHelper } from './use-block-suite-meta-helper';
|
||||
@@ -69,7 +69,7 @@ export function getDragItemId(
|
||||
|
||||
export const useSidebarDrag = () => {
|
||||
const t = useAFFiNEI18N();
|
||||
const currentWorkspace = useAtomValue(waitForCurrentWorkspaceAtom);
|
||||
const currentWorkspace = useService(Workspace);
|
||||
const workspace = currentWorkspace.blockSuiteWorkspace;
|
||||
const { setTrashModal } = useTrashModalHelper(workspace);
|
||||
const { addToFavorite, removeFromFavorite } =
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { useBlockSuiteWorkspacePage } from '@affine/core/hooks/use-block-suite-workspace-page';
|
||||
import { waitForCurrentWorkspaceAtom } from '@affine/core/modules/workspace';
|
||||
import { Workspace } from '@toeverything/infra';
|
||||
import { useService } from '@toeverything/infra/di';
|
||||
import { useAtomValue } from 'jotai';
|
||||
|
||||
import { currentPageIdAtom } from '../../atoms/mode';
|
||||
|
||||
export const useCurrentPage = () => {
|
||||
const currentPageId = useAtomValue(currentPageIdAtom);
|
||||
const currentWorkspace = useAtomValue(waitForCurrentWorkspaceAtom);
|
||||
|
||||
const currentWorkspace = useService(Workspace);
|
||||
return useBlockSuiteWorkspacePage(
|
||||
currentWorkspace?.blockSuiteWorkspace,
|
||||
currentWorkspace.blockSuiteWorkspace,
|
||||
currentPageId
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
import type { Workspace } from '@blocksuite/store';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import { useService } from '@toeverything/infra/di';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import type { WorkspacePropertiesAdapter } from '../modules/workspace/properties';
|
||||
import {
|
||||
currentWorkspacePropertiesAdapterAtom,
|
||||
workspaceAdapterAtomFamily,
|
||||
} from '../modules/workspace/properties';
|
||||
import { WorkspacePropertiesAdapter } from '../modules/workspace/properties';
|
||||
|
||||
function getProxy<T extends object>(obj: T) {
|
||||
return new Proxy(obj, {});
|
||||
@@ -31,11 +26,6 @@ const useReactiveAdapter = (adapter: WorkspacePropertiesAdapter) => {
|
||||
};
|
||||
|
||||
export function useCurrentWorkspacePropertiesAdapter() {
|
||||
const adapter = useAtomValue(currentWorkspacePropertiesAdapterAtom);
|
||||
return useReactiveAdapter(adapter);
|
||||
}
|
||||
|
||||
export function useWorkspacePropertiesAdapter(workspace: Workspace) {
|
||||
const adapter = useAtomValue(workspaceAdapterAtomFamily(workspace));
|
||||
const adapter = useService(WorkspacePropertiesAdapter);
|
||||
return useReactiveAdapter(adapter);
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import { useCallback, useSyncExternalStore } from 'react';
|
||||
import type { DataSourceAdapter, Status } from 'y-provider';
|
||||
|
||||
type UIStatus =
|
||||
| Status
|
||||
| {
|
||||
type: 'unknown';
|
||||
};
|
||||
|
||||
export function useDataSourceStatus(provider: DataSourceAdapter): UIStatus {
|
||||
return useSyncExternalStore(
|
||||
provider.subscribeStatusChange,
|
||||
useCallback(() => provider.status, [provider])
|
||||
);
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import { useCallback, useMemo } from 'react';
|
||||
|
||||
import type { BlockSuiteWorkspace } from '../shared';
|
||||
import { timestampToLocalDate } from '../utils';
|
||||
import { useWorkspacePropertiesAdapter } from './use-affine-adapter';
|
||||
import { useCurrentWorkspacePropertiesAdapter } from './use-affine-adapter';
|
||||
import { useBlockSuiteWorkspaceHelper } from './use-block-suite-workspace-helper';
|
||||
import { useNavigateHelper } from './use-navigate-helper';
|
||||
|
||||
@@ -24,7 +24,7 @@ function toDayjs(j?: string | false) {
|
||||
|
||||
export const useJournalHelper = (workspace: BlockSuiteWorkspace) => {
|
||||
const bsWorkspaceHelper = useBlockSuiteWorkspaceHelper(workspace);
|
||||
const adapter = useWorkspacePropertiesAdapter(workspace);
|
||||
const adapter = useCurrentWorkspacePropertiesAdapter();
|
||||
|
||||
/**
|
||||
* @internal
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { waitForCurrentWorkspaceAtom } from '@affine/core/modules/workspace';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { useAtomValue, useSetAtom, useStore } from 'jotai';
|
||||
import { Workspace } from '@toeverything/infra';
|
||||
import { useService } from '@toeverything/infra/di';
|
||||
import { useSetAtom, useStore } from 'jotai';
|
||||
import { useTheme } from 'next-themes';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
@@ -22,7 +23,7 @@ export function useRegisterWorkspaceCommands() {
|
||||
const store = useStore();
|
||||
const t = useAFFiNEI18N();
|
||||
const theme = useTheme();
|
||||
const currentWorkspace = useAtomValue(waitForCurrentWorkspaceAtom);
|
||||
const currentWorkspace = useService(Workspace);
|
||||
const languageHelper = useLanguageHelper();
|
||||
const pageHelper = usePageHelper(currentWorkspace.blockSuiteWorkspace);
|
||||
const navigationHelper = useNavigateHelper();
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { workspaceManagerAtom } from '@affine/core/modules/workspace';
|
||||
import type { WorkspaceMetadata } from '@affine/workspace/metadata';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import type { WorkspaceMetadata } from '@toeverything/infra';
|
||||
import { WorkspaceManager } from '@toeverything/infra';
|
||||
import { useService } from '@toeverything/infra';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export function useWorkspaceBlobObjectUrl(
|
||||
meta?: WorkspaceMetadata,
|
||||
blobKey?: string | null
|
||||
) {
|
||||
const workspaceManager = useAtomValue(workspaceManagerAtom);
|
||||
const workspaceManager = useService(WorkspaceManager);
|
||||
|
||||
const [blob, setBlob] = useState<string | undefined>(undefined);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
enabledFeaturesQuery,
|
||||
setWorkspaceExperimentalFeatureMutation,
|
||||
} from '@affine/graphql';
|
||||
import type { WorkspaceMetadata } from '@affine/workspace/metadata';
|
||||
import { type WorkspaceMetadata } from '@toeverything/infra';
|
||||
|
||||
import { useAsyncCallback } from './affine-async-hooks';
|
||||
import { useMutateQueryResource, useMutation } from './use-mutation';
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { workspaceManagerAtom } from '@affine/core/modules/workspace';
|
||||
import type { WorkspaceMetadata } from '@affine/workspace';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import { WorkspaceManager, type WorkspaceMetadata } from '@toeverything/infra';
|
||||
import { useService } from '@toeverything/infra/di';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { useWorkspaceBlobObjectUrl } from './use-workspace-blob';
|
||||
|
||||
export function useWorkspaceInfo(meta: WorkspaceMetadata) {
|
||||
const workspaceManager = useAtomValue(workspaceManagerAtom);
|
||||
const workspaceManager = useService(WorkspaceManager);
|
||||
|
||||
const [information, setInformation] = useState(
|
||||
() => workspaceManager.list.getInformation(meta).info
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Workspace, WorkspaceStatus } from '@affine/workspace';
|
||||
import type { Workspace, WorkspaceStatus } from '@toeverything/infra';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export function useWorkspaceStatus<
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { workspaceManagerAtom } from '@affine/core/modules/workspace';
|
||||
import type { Workspace } from '@affine/workspace';
|
||||
import type { WorkspaceMetadata } from '@affine/workspace/metadata';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import type { WorkspaceMetadata } from '@toeverything/infra';
|
||||
import { type Workspace, WorkspaceManager } from '@toeverything/infra';
|
||||
import { useService } from '@toeverything/infra/di';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
/**
|
||||
* definitely be careful when using this hook, open workspace is a heavy operation
|
||||
*/
|
||||
export function useWorkspace(meta?: WorkspaceMetadata | null) {
|
||||
const workspaceManager = useAtomValue(workspaceManagerAtom);
|
||||
const workspaceManager = useService(WorkspaceManager);
|
||||
|
||||
const [workspace, setWorkspace] = useState<Workspace | null>(null);
|
||||
|
||||
@@ -17,7 +16,7 @@ export function useWorkspace(meta?: WorkspaceMetadata | null) {
|
||||
setWorkspace(null); // set to null if meta is null or undefined
|
||||
return;
|
||||
}
|
||||
const ref = workspaceManager.use(meta);
|
||||
const ref = workspaceManager.open(meta);
|
||||
setWorkspace(ref.workspace);
|
||||
return () => {
|
||||
ref.release();
|
||||
|
||||
Reference in New Issue
Block a user