mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-01 17:50:50 +08:00
feat(infra): page infra (#5618)
This commit is contained in:
@@ -4,12 +4,14 @@ export * from './blocksuite';
|
|||||||
export * from './command';
|
export * from './command';
|
||||||
export * from './di';
|
export * from './di';
|
||||||
export * from './livedata';
|
export * from './livedata';
|
||||||
|
export * from './page';
|
||||||
export * from './storage';
|
export * from './storage';
|
||||||
export * from './utils';
|
export * from './utils';
|
||||||
export * from './workspace';
|
export * from './workspace';
|
||||||
|
|
||||||
import type { ServiceCollection } from './di';
|
import type { ServiceCollection } from './di';
|
||||||
import { CleanupService } from './lifecycle';
|
import { CleanupService } from './lifecycle';
|
||||||
|
import { configurePageServices } from './page';
|
||||||
import { GlobalCache, GlobalState, MemoryMemento } from './storage';
|
import { GlobalCache, GlobalState, MemoryMemento } from './storage';
|
||||||
import {
|
import {
|
||||||
configureTestingWorkspaceServices,
|
configureTestingWorkspaceServices,
|
||||||
@@ -19,6 +21,7 @@ import {
|
|||||||
export function configureInfraServices(services: ServiceCollection) {
|
export function configureInfraServices(services: ServiceCollection) {
|
||||||
services.add(CleanupService);
|
services.add(CleanupService);
|
||||||
configureWorkspaceServices(services);
|
configureWorkspaceServices(services);
|
||||||
|
configurePageServices(services);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function configureTestingInfraServices(services: ServiceCollection) {
|
export function configureTestingInfraServices(services: ServiceCollection) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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]);
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import { createScope, type ServiceScope } from '../di';
|
||||||
|
import { WorkspaceScope } from '../workspace';
|
||||||
|
|
||||||
|
export const PageScope: ServiceScope = createScope('page', WorkspaceScope);
|
||||||
Reference in New Issue
Block a user