From 4b5d1de20673068919ea41ec378975ed8f76bb30 Mon Sep 17 00:00:00 2001 From: EYHN Date: Wed, 12 Mar 2025 05:02:04 +0000 Subject: [PATCH] feat(core): add blocksuite writer info service (#10754) --- .../shared/src/services/block-meta-service.ts | 26 +++++------ .../shared/src/services/user-service/index.ts | 1 + .../src/services/user-service/user-service.ts | 1 - .../user-service/writer-info-service.ts | 22 +++++++++ .../block-suite-editor/lit-adaper.tsx | 7 +-- .../core/src/blocksuite/extensions/user.ts | 20 +------- .../frontend/core/src/modules/cloud/index.ts | 12 ++--- .../cloud/services/blocksuite-writer-info.ts | 46 +++++++++++++++++++ .../services/editor-user-cursor-label.ts | 27 ----------- .../core/src/modules/workspace/impls/doc.ts | 7 ++- .../src/modules/workspace/services/repo.ts | 2 +- 11 files changed, 96 insertions(+), 75 deletions(-) create mode 100644 blocksuite/affine/shared/src/services/user-service/writer-info-service.ts create mode 100644 packages/frontend/core/src/modules/cloud/services/blocksuite-writer-info.ts delete mode 100644 packages/frontend/core/src/modules/cloud/services/editor-user-cursor-label.ts diff --git a/blocksuite/affine/shared/src/services/block-meta-service.ts b/blocksuite/affine/shared/src/services/block-meta-service.ts index fbbc01f36..05cb12194 100644 --- a/blocksuite/affine/shared/src/services/block-meta-service.ts +++ b/blocksuite/affine/shared/src/services/block-meta-service.ts @@ -2,7 +2,7 @@ import type { BlockMeta } from '@blocksuite/affine-model'; import { type BlockModel, StoreExtension } from '@blocksuite/store'; import { FeatureFlagService } from './feature-flag-service'; -import { UserProvider } from './user-service'; +import { WriterInfoProvider } from './user-service'; /** * The service is used to add following info to the block. @@ -43,20 +43,20 @@ export class BlockMetaService extends StoreExtension { return; } - const currentUser = this._getCurrentUser(); - if (!currentUser) return; + const writer = this._getWriterInfo(); + if (!writer) return; const now = getNow(); this.store.withoutTransact(() => { const isFlatModel = model.schema.model.isFlatData; if (!isFlatModel) { model['meta:createdAt'] = now; - model['meta:createdBy'] = currentUser.id; + model['meta:createdBy'] = writer.id; return; } model.props['meta:createdAt'] = now; - model.props['meta:createdBy'] = currentUser.id; + model.props['meta:createdBy'] = writer.id; }); }; @@ -65,33 +65,33 @@ export class BlockMetaService extends StoreExtension { return; } - const currentUser = this._getCurrentUser(); - if (!currentUser) return; + const writer = this._getWriterInfo(); + if (!writer) return; const now = getNow(); this.store.withoutTransact(() => { const isFlatModel = model.schema.model.isFlatData; if (!isFlatModel) { model['meta:updatedAt'] = now; - model['meta:updatedBy'] = currentUser.id; + model['meta:updatedBy'] = writer.id; if (!model['meta:createdAt']) { model['meta:createdAt'] = now; - model['meta:createdBy'] = currentUser.id; + model['meta:createdBy'] = writer.id; } return; } model.props['meta:updatedAt'] = now; - model.props['meta:updatedBy'] = currentUser.id; + model.props['meta:updatedBy'] = writer.id; if (!model.props['meta:createdAt']) { model.props['meta:createdAt'] = now; - model.props['meta:createdBy'] = currentUser.id; + model.props['meta:createdBy'] = writer.id; } }); }; - private readonly _getCurrentUser = () => { - return this.store.getOptional(UserProvider)?.getCurrentUser(); + private readonly _getWriterInfo = () => { + return this.store.getOptional(WriterInfoProvider)?.getWriterInfo(); }; } diff --git a/blocksuite/affine/shared/src/services/user-service/index.ts b/blocksuite/affine/shared/src/services/user-service/index.ts index 2a4ac6160..408af31c6 100644 --- a/blocksuite/affine/shared/src/services/user-service/index.ts +++ b/blocksuite/affine/shared/src/services/user-service/index.ts @@ -1,3 +1,4 @@ export * from './types'; export * from './user-list-service'; export * from './user-service'; +export * from './writer-info-service'; diff --git a/blocksuite/affine/shared/src/services/user-service/user-service.ts b/blocksuite/affine/shared/src/services/user-service/user-service.ts index 129ac1dcf..5095f5a4f 100644 --- a/blocksuite/affine/shared/src/services/user-service/user-service.ts +++ b/blocksuite/affine/shared/src/services/user-service/user-service.ts @@ -5,7 +5,6 @@ import type { Signal } from '@preact/signals-core'; import type { AffineUserInfo } from './types'; export interface UserService { - getCurrentUser(): AffineUserInfo | null; userInfo$(id: string): Signal; revalidateUserInfo(id: string): void; } diff --git a/blocksuite/affine/shared/src/services/user-service/writer-info-service.ts b/blocksuite/affine/shared/src/services/user-service/writer-info-service.ts new file mode 100644 index 000000000..37a23a8b5 --- /dev/null +++ b/blocksuite/affine/shared/src/services/user-service/writer-info-service.ts @@ -0,0 +1,22 @@ +import { createIdentifier } from '@blocksuite/global/di'; +import type { ExtensionType } from '@blocksuite/store'; + +import type { AffineUserInfo } from './types'; + +export interface WriterInfoService { + getWriterInfo(): AffineUserInfo | null; +} + +export const WriterInfoProvider = createIdentifier( + 'affine-writer-info-service' +); + +export function WriterInfoServiceExtension( + service: WriterInfoService +): ExtensionType { + return { + setup(di) { + di.addImpl(WriterInfoProvider, () => service); + }, + }; +} diff --git a/packages/frontend/core/src/blocksuite/block-suite-editor/lit-adaper.tsx b/packages/frontend/core/src/blocksuite/block-suite-editor/lit-adaper.tsx index ce5622df9..1fc8004d3 100644 --- a/packages/frontend/core/src/blocksuite/block-suite-editor/lit-adaper.tsx +++ b/packages/frontend/core/src/blocksuite/block-suite-editor/lit-adaper.tsx @@ -7,7 +7,7 @@ import { type PageEditor, } from '@affine/core/blocksuite/editors'; import { useEnableAI } from '@affine/core/components/hooks/affine/use-enable-ai'; -import { AuthService, PublicUserService } from '@affine/core/modules/cloud'; +import { PublicUserService } from '@affine/core/modules/cloud'; import type { DocCustomPropertyInfo } from '@affine/core/modules/db'; import { DocService, DocsService } from '@affine/core/modules/doc'; import type { @@ -94,7 +94,6 @@ const usePatchSpecs = (mode: DocMode) => { featureFlagService, memberSearchService, publicUserService, - authService, } = useServices({ PeekViewService, DocService, @@ -104,7 +103,6 @@ const usePatchSpecs = (mode: DocMode) => { FeatureFlagService, MemberSearchService, PublicUserService, - AuthService, }); const isCloud = workspaceService.workspace.flavour !== 'local'; const framework = useFramework(); @@ -167,7 +165,7 @@ const usePatchSpecs = (mode: DocMode) => { isCloud ? [ patchUserListExtensions(memberSearchService), - patchUserExtensions(publicUserService, authService), + patchUserExtensions(publicUserService), ] : [], mode === 'edgeless' && enableTurboRenderer @@ -201,7 +199,6 @@ const usePatchSpecs = (mode: DocMode) => { isCloud, memberSearchService, publicUserService, - authService, enableTurboRenderer, featureFlagService.flags.enable_pdf_embed_preview.value, ]); diff --git a/packages/frontend/core/src/blocksuite/extensions/user.ts b/packages/frontend/core/src/blocksuite/extensions/user.ts index a68c76051..e8870f769 100644 --- a/packages/frontend/core/src/blocksuite/extensions/user.ts +++ b/packages/frontend/core/src/blocksuite/extensions/user.ts @@ -1,24 +1,8 @@ -import type { - AuthService, - PublicUserService, -} from '@affine/core/modules/cloud'; +import type { PublicUserService } from '@affine/core/modules/cloud'; import { UserServiceExtension } from '@blocksuite/affine/shared/services'; -export function patchUserExtensions( - publicUserService: PublicUserService, - authService: AuthService -) { +export function patchUserExtensions(publicUserService: PublicUserService) { return UserServiceExtension({ - getCurrentUser() { - const account = authService.session.account$.value; - return account - ? { - id: account.id, - avatar: account.avatar, - name: account.label, - } - : null; - }, // eslint-disable-next-line rxjs/finnish userInfo$(id) { return publicUserService.publicUser$(id).signal; diff --git a/packages/frontend/core/src/modules/cloud/index.ts b/packages/frontend/core/src/modules/cloud/index.ts index 19303e0f9..195e70ae8 100644 --- a/packages/frontend/core/src/modules/cloud/index.ts +++ b/packages/frontend/core/src/modules/cloud/index.ts @@ -33,7 +33,6 @@ import { type Framework } from '@toeverything/infra'; import { DocScope } from '../doc/scopes/doc'; import { DocService } from '../doc/services/doc'; -import { EditorScope } from '../editor'; import { GlobalCache, GlobalState } from '../storage/providers/global'; import { GlobalStateService } from '../storage/services/global'; import { UrlService } from '../url'; @@ -55,10 +54,10 @@ import { ValidatorProvider } from './provider/validator'; import { ServerScope } from './scopes/server'; import { AcceptInviteService } from './services/accept-invite'; import { AuthService } from './services/auth'; +import { BlocksuiteWriterInfoService } from './services/blocksuite-writer-info'; import { CaptchaService } from './services/captcha'; import { CloudDocMetaService } from './services/cloud-doc-meta'; import { DefaultServerService } from './services/default-server'; -import { EditorUserCursorLabelService } from './services/editor-user-cursor-label'; import { EventSourceService } from './services/eventsource'; import { FetchService } from './services/fetch'; import { GraphQLService } from './services/graphql'; @@ -167,11 +166,6 @@ export function configureCloudModule(framework: Framework) { .service(WorkspaceInvoicesService) .entity(WorkspaceInvoices, [WorkspaceService, WorkspaceServerService]) .service(SelfhostLicenseService, [SelfhostLicenseStore, WorkspaceService]) - .store(SelfhostLicenseStore, [WorkspaceServerService]); - - framework - .scope(WorkspaceScope) - .scope(DocScope) - .scope(EditorScope) - .service(EditorUserCursorLabelService, [WorkspaceServerService]); + .store(SelfhostLicenseStore, [WorkspaceServerService]) + .service(BlocksuiteWriterInfoService, [WorkspaceServerService]); } diff --git a/packages/frontend/core/src/modules/cloud/services/blocksuite-writer-info.ts b/packages/frontend/core/src/modules/cloud/services/blocksuite-writer-info.ts new file mode 100644 index 000000000..78e181c4e --- /dev/null +++ b/packages/frontend/core/src/modules/cloud/services/blocksuite-writer-info.ts @@ -0,0 +1,46 @@ +import { WriterInfoServiceExtension } from '@blocksuite/affine/shared/services'; +import { OnEvent, Service } from '@toeverything/infra'; + +import { type Workspace, WorkspaceInitialized } from '../../workspace'; +import type { DocImpl } from '../../workspace/impls/doc'; +import type { WorkspaceServerService } from './workspace-server'; + +/** + * This service is used to set the writer info for the blocksuite editor. + */ +@OnEvent(WorkspaceInitialized, i => i.onWorkspaceInitialized) +export class BlocksuiteWriterInfoService extends Service { + constructor(private readonly workspaceServerService: WorkspaceServerService) { + super(); + } + + onWorkspaceInitialized(workspace: Workspace) { + const setWriterInfo = (doc: DocImpl) => { + const account = this.workspaceServerService.server?.account$.value; + doc.awarenessStore.awareness.setLocalStateField('user', { + name: account?.label, + }); + doc.storeExtensions.push( + WriterInfoServiceExtension({ + getWriterInfo: () => { + if (!account) { + return null; + } + return { + id: account.id, + name: account.label, + avatar: account.avatar, + }; + }, + }) + ); + }; + const subscription = workspace.docCollection.meta.docMetaAdded.subscribe( + docId => { + const doc = workspace.docCollection.docs.get(docId) as DocImpl; + setWriterInfo(doc); + } + ); + this.disposables.push(() => subscription.unsubscribe.bind(subscription)); + } +} diff --git a/packages/frontend/core/src/modules/cloud/services/editor-user-cursor-label.ts b/packages/frontend/core/src/modules/cloud/services/editor-user-cursor-label.ts deleted file mode 100644 index 4ff455e95..000000000 --- a/packages/frontend/core/src/modules/cloud/services/editor-user-cursor-label.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { OnEvent, Service } from '@toeverything/infra'; - -import type { Editor } from '../../editor'; -import { EditorInitialized } from '../../editor/events'; -import type { WorkspaceServerService } from './workspace-server'; - -@OnEvent(EditorInitialized, i => i.onEditorInitialized) -export class EditorUserCursorLabelService extends Service { - constructor(private readonly workspaceServerService: WorkspaceServerService) { - super(); - } - - onEditorInitialized(editor: Editor) { - if (this.workspaceServerService.server) { - const subscription = - this.workspaceServerService.server.account$.subscribe(account => { - editor.doc.blockSuiteDoc.awarenessStore.awareness.setLocalStateField( - 'user', - { - name: account?.label, - } - ); - }); - this.disposables.push(() => subscription.unsubscribe()); - } - } -} diff --git a/packages/frontend/core/src/modules/workspace/impls/doc.ts b/packages/frontend/core/src/modules/workspace/impls/doc.ts index c9df4a553..a8c8ab81c 100644 --- a/packages/frontend/core/src/modules/workspace/impls/doc.ts +++ b/packages/frontend/core/src/modules/workspace/impls/doc.ts @@ -2,6 +2,7 @@ import { SpecProvider } from '@blocksuite/affine/shared/utils'; import { AwarenessStore, type Doc, + type ExtensionType, type GetBlocksOptions, type Query, Store, @@ -92,6 +93,8 @@ export class DocImpl implements Doc { */ protected readonly _ySpaceDoc: Y.Doc; + readonly storeExtensions: ExtensionType[] = []; + readonly awarenessStore: AwarenessStore; readonly id: string; @@ -284,7 +287,9 @@ export class DocImpl implements Doc { const storeExtensions = SpecProvider._.getSpec('store'); const extensionSet = new Set( - storeExtensions.value.concat(extensions ?? []) + storeExtensions.value + .concat(extensions ?? []) + .concat(this.storeExtensions) ); const doc = new Store({ diff --git a/packages/frontend/core/src/modules/workspace/services/repo.ts b/packages/frontend/core/src/modules/workspace/services/repo.ts index 0c9c94a18..f2c882e4c 100644 --- a/packages/frontend/core/src/modules/workspace/services/repo.ts +++ b/packages/frontend/core/src/modules/workspace/services/repo.ts @@ -110,7 +110,7 @@ export class WorkspaceRepositoryService extends Service { workspace.engine.start(); - this.framework.emitEvent(WorkspaceInitialized, workspace); + workspaceScope.emitEvent(WorkspaceInitialized, workspace); flavourProvider?.onWorkspaceInitialized?.(workspace);