feat(infra): page infra (#5618)
This commit is contained in:
parent
2e71c980cf
commit
1e3499c323
@ -4,12 +4,14 @@ export * from './blocksuite';
|
||||
export * from './command';
|
||||
export * from './di';
|
||||
export * from './livedata';
|
||||
export * from './page';
|
||||
export * from './storage';
|
||||
export * from './utils';
|
||||
export * from './workspace';
|
||||
|
||||
import type { ServiceCollection } from './di';
|
||||
import { CleanupService } from './lifecycle';
|
||||
import { configurePageServices } from './page';
|
||||
import { GlobalCache, GlobalState, MemoryMemento } from './storage';
|
||||
import {
|
||||
configureTestingWorkspaceServices,
|
||||
@ -19,6 +21,7 @@ import {
|
||||
export function configureInfraServices(services: ServiceCollection) {
|
||||
services.add(CleanupService);
|
||||
configureWorkspaceServices(services);
|
||||
configurePageServices(services);
|
||||
}
|
||||
|
||||
export function configureTestingInfraServices(services: ServiceCollection) {
|
||||
|
31
packages/common/infra/src/page/__tests__/page.spec.ts
Normal file
31
packages/common/infra/src/page/__tests__/page.spec.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||
import { describe, expect, test } from 'vitest';
|
||||
|
||||
import { configureInfraServices, configureTestingInfraServices } from '../..';
|
||||
import { ServiceCollection } from '../../di';
|
||||
import { WorkspaceManager } from '../../workspace';
|
||||
import { PageListService } from '..';
|
||||
|
||||
describe('Page System', () => {
|
||||
test('basic', async () => {
|
||||
const services = new ServiceCollection();
|
||||
configureInfraServices(services);
|
||||
configureTestingInfraServices(services);
|
||||
|
||||
const provider = services.provider();
|
||||
const workspaceManager = provider.get(WorkspaceManager);
|
||||
|
||||
const { workspace } = workspaceManager.open(
|
||||
await workspaceManager.createWorkspace(WorkspaceFlavour.LOCAL)
|
||||
);
|
||||
|
||||
const pageListService = workspace.services.get(PageListService);
|
||||
expect(pageListService.pages.value.length).toBe(0);
|
||||
|
||||
workspace.blockSuiteWorkspace.createPage({
|
||||
id: 'page0',
|
||||
});
|
||||
|
||||
expect(pageListService.pages.value.length).toBe(1);
|
||||
});
|
||||
});
|
21
packages/common/infra/src/page/context.ts
Normal file
21
packages/common/infra/src/page/context.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import type { Page as BlockSuitePage, PageMeta } from '@blocksuite/store';
|
||||
|
||||
import { createIdentifier, type ServiceCollection } from '../di';
|
||||
import { PageScope } from './service-scope';
|
||||
|
||||
export const BlockSuitePageContext = createIdentifier<BlockSuitePage>(
|
||||
'BlockSuitePageContext'
|
||||
);
|
||||
|
||||
export const PageMetaContext = createIdentifier<PageMeta>('PageMetaContext');
|
||||
|
||||
export function configurePageContext(
|
||||
services: ServiceCollection,
|
||||
blockSuitePage: BlockSuitePage,
|
||||
pageMeta: PageMeta
|
||||
) {
|
||||
services
|
||||
.scope(PageScope)
|
||||
.addImpl(PageMetaContext, pageMeta)
|
||||
.addImpl(BlockSuitePageContext, blockSuitePage);
|
||||
}
|
25
packages/common/infra/src/page/index.ts
Normal file
25
packages/common/infra/src/page/index.ts
Normal file
@ -0,0 +1,25 @@
|
||||
export * from './context';
|
||||
export * from './list';
|
||||
export * from './manager';
|
||||
export * from './page';
|
||||
export * from './service-scope';
|
||||
|
||||
import { type ServiceCollection, ServiceProvider } from '../di';
|
||||
import { CleanupService } from '../lifecycle';
|
||||
import { Workspace, WorkspaceScope } from '../workspace';
|
||||
import { BlockSuitePageContext, PageMetaContext } from './context';
|
||||
import { PageListService } from './list';
|
||||
import { PageManager } from './manager';
|
||||
import { Page } from './page';
|
||||
import { PageScope } from './service-scope';
|
||||
|
||||
export function configurePageServices(services: ServiceCollection) {
|
||||
services
|
||||
.scope(WorkspaceScope)
|
||||
.add(PageListService, [Workspace])
|
||||
.add(PageManager, [Workspace, ServiceProvider]);
|
||||
services
|
||||
.scope(PageScope)
|
||||
.add(CleanupService)
|
||||
.add(Page, [PageMetaContext, BlockSuitePageContext, ServiceProvider]);
|
||||
}
|
28
packages/common/infra/src/page/list.ts
Normal file
28
packages/common/infra/src/page/list.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import type { PageMeta } from '@blocksuite/store';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { LiveData } from '../livedata';
|
||||
import type { Workspace } from '../workspace';
|
||||
|
||||
export class PageListService {
|
||||
constructor(private readonly workspace: Workspace) {}
|
||||
|
||||
public readonly pages = LiveData.from<PageMeta[]>(
|
||||
new Observable(subscriber => {
|
||||
subscriber.next(
|
||||
Array.from(this.workspace.blockSuiteWorkspace.meta.pageMetas)
|
||||
);
|
||||
|
||||
const dispose =
|
||||
this.workspace.blockSuiteWorkspace.meta.pageMetasUpdated.on(() => {
|
||||
subscriber.next(
|
||||
Array.from(this.workspace.blockSuiteWorkspace.meta.pageMetas)
|
||||
);
|
||||
}).dispose;
|
||||
return () => {
|
||||
dispose();
|
||||
};
|
||||
}),
|
||||
[]
|
||||
);
|
||||
}
|
46
packages/common/infra/src/page/manager.ts
Normal file
46
packages/common/infra/src/page/manager.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import type { PageMeta } from '@blocksuite/store';
|
||||
|
||||
import type { ServiceProvider } from '../di';
|
||||
import { ObjectPool, type RcRef } from '../utils/object-pool';
|
||||
import type { Workspace } from '../workspace';
|
||||
import { configurePageContext } from './context';
|
||||
import { Page } from './page';
|
||||
import { PageScope } from './service-scope';
|
||||
|
||||
export class PageManager {
|
||||
pool = new ObjectPool<string, Page>({});
|
||||
|
||||
constructor(
|
||||
private readonly workspace: Workspace,
|
||||
private readonly serviceProvider: ServiceProvider
|
||||
) {}
|
||||
|
||||
open(pageMeta: PageMeta): RcRef<Page> {
|
||||
const blockSuitePage = this.workspace.blockSuiteWorkspace.getPage(
|
||||
pageMeta.id
|
||||
);
|
||||
if (!blockSuitePage) {
|
||||
throw new Error('Page not found');
|
||||
}
|
||||
|
||||
const exists = this.pool.get(pageMeta.id);
|
||||
if (exists) {
|
||||
return exists;
|
||||
}
|
||||
|
||||
const serviceCollection = this.serviceProvider.collection
|
||||
// avoid to modify the original service collection
|
||||
.clone();
|
||||
|
||||
configurePageContext(serviceCollection, blockSuitePage, pageMeta);
|
||||
|
||||
const provider = serviceCollection.provider(
|
||||
PageScope,
|
||||
this.serviceProvider
|
||||
);
|
||||
|
||||
const page = provider.get(Page);
|
||||
|
||||
return this.pool.put(pageMeta.id, page);
|
||||
}
|
||||
}
|
15
packages/common/infra/src/page/page.ts
Normal file
15
packages/common/infra/src/page/page.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import type { Page as BlockSuitePage } from '@blocksuite/store';
|
||||
import { type PageMeta } from '@blocksuite/store';
|
||||
import type { ServiceProvider } from '@toeverything/infra/di';
|
||||
|
||||
export class Page {
|
||||
get id() {
|
||||
return this.meta.id;
|
||||
}
|
||||
|
||||
constructor(
|
||||
public readonly meta: PageMeta,
|
||||
public readonly blockSuitePage: BlockSuitePage,
|
||||
public readonly services: ServiceProvider
|
||||
) {}
|
||||
}
|
4
packages/common/infra/src/page/service-scope.ts
Normal file
4
packages/common/infra/src/page/service-scope.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import { createScope, type ServiceScope } from '../di';
|
||||
import { WorkspaceScope } from '../workspace';
|
||||
|
||||
export const PageScope: ServiceScope = createScope('page', WorkspaceScope);
|
Loading…
x
Reference in New Issue
Block a user