feat(editor): replace slot with rxjs subject (#10768)

This commit is contained in:
Mirone
2025-03-12 11:29:24 +09:00
committed by GitHub
parent 19f978d9aa
commit cd63e0ed8b
302 changed files with 1405 additions and 1251 deletions
@@ -52,7 +52,7 @@ export class AuthService extends Service {
skip(1) // skip the initial value
)
.subscribe(({ account }) => {
AIProvider.slots.userInfo.emit(toAIUserInfo(account));
AIProvider.slots.userInfo.next(toAIUserInfo(account));
if (account === null) {
this.eventBus.emit(AccountLoggedOut, account);
@@ -17,7 +17,7 @@ export class EditorSettingService extends Service {
onWorkspaceInitialized(workspace: Workspace) {
// set default mode for new doc
workspace.docCollection.slots.docCreated.on(docId => {
workspace.docCollection.slots.docCreated.subscribe(docId => {
const preferMode = this.editorSetting.settings$.value.newDocDefaultMode;
const docsService = workspace.scope.get(DocsService);
const mode = preferMode === 'ask' ? 'page' : preferMode;
@@ -261,7 +261,9 @@ export class Editor extends Entity {
scrollViewport?.removeEventListener('scroll', saveScrollPosition);
});
if (gfx) {
unsubs.push(gfx.viewport.viewportUpdated.on(saveScrollPosition).dispose);
const subscription =
gfx.viewport.viewportUpdated.subscribe(saveScrollPosition);
unsubs.push(subscription.unsubscribe.bind(subscription));
}
// update selection when focusAt$ changed
@@ -9,11 +9,8 @@ import { EditorService } from '@affine/core/modules/editor';
import { GuardService } from '@affine/core/modules/permissions';
import { DebugLogger } from '@affine/debug';
import { GfxControllerIdentifier } from '@blocksuite/affine/block-std/gfx';
import { DisposableGroup } from '@blocksuite/affine/global/disposable';
import { Bound } from '@blocksuite/affine/global/gfx';
import {
type Disposable,
DisposableGroup,
} from '@blocksuite/affine/global/slot';
import { RefNodeSlotsProvider } from '@blocksuite/affine/rich-text';
import {
FrameworkScope,
@@ -23,6 +20,7 @@ import {
} from '@toeverything/infra';
import clsx from 'clsx';
import { lazy, Suspense, useCallback, useEffect } from 'react';
import type { Subscription } from 'rxjs';
import { WorkbenchService } from '../../../workbench';
import type { DocReferenceInfo } from '../../entities/peek-view';
@@ -101,7 +99,7 @@ function DocPeekPreviewEditor({
// doc change event inside peek view should be handled by peek view
disposableGroup.add(
// todo(@pengx17): seems not working
refNodeSlots.docLinkClicked.on(options => {
refNodeSlots.docLinkClicked.subscribe(options => {
if (options.host !== editorContainer.host) {
return;
}
@@ -129,7 +127,7 @@ function DocPeekPreviewEditor({
);
useEffect(() => {
const disposables: Disposable[] = [];
const disposables: Subscription[] = [];
const openHandler = () => {
if (doc) {
workbench.openDoc(doc.id);
@@ -137,9 +135,13 @@ function DocPeekPreviewEditor({
// chat panel open is already handled in <DetailPageImpl />
}
};
disposables.push(AIProvider.slots.requestOpenWithChat.on(openHandler));
disposables.push(AIProvider.slots.requestSendWithChat.on(openHandler));
return () => disposables.forEach(d => d.dispose());
disposables.push(
AIProvider.slots.requestOpenWithChat.subscribe(openHandler)
);
disposables.push(
AIProvider.slots.requestSendWithChat.subscribe(openHandler)
);
return () => disposables.forEach(d => d.unsubscribe());
}, [doc, peekView, workbench, workspace.id]);
const openOutlinePanel = useCallback(() => {
@@ -23,8 +23,10 @@ export class TagStore extends Store {
subscribe(cb: () => void) {
const disposable =
this.workspaceService.workspace.docCollection.slots.docListUpdated.on(cb);
return disposable.dispose;
this.workspaceService.workspace.docCollection.slots.docListUpdated.subscribe(
cb
);
return disposable.unsubscribe.bind(disposable);
}
constructor(private readonly workspaceService: WorkspaceService) {
@@ -73,9 +73,11 @@ export class Workspace extends Entity {
name$ = LiveData.from<string | undefined>(
new Observable(subscriber => {
subscriber.next(this.docCollection.meta.name);
return this.docCollection.meta.commonFieldsUpdated.on(() => {
subscriber.next(this.docCollection.meta.name);
}).dispose;
const subscription =
this.docCollection.meta.commonFieldsUpdated.subscribe(() => {
subscriber.next(this.docCollection.meta.name);
});
return subscription.unsubscribe.bind(subscription);
}),
undefined
);
@@ -83,9 +85,11 @@ export class Workspace extends Entity {
avatar$ = LiveData.from<string | undefined>(
new Observable(subscriber => {
subscriber.next(this.docCollection.meta.avatar);
return this.docCollection.meta.commonFieldsUpdated.on(() => {
subscriber.next(this.docCollection.meta.avatar);
}).dispose;
const subscription =
this.docCollection.meta.commonFieldsUpdated.subscribe(() => {
subscriber.next(this.docCollection.meta.avatar);
});
return subscription.unsubscribe.bind(subscription);
}),
undefined
);
@@ -1,4 +1,3 @@
import { Slot } from '@blocksuite/affine/global/slot';
import { SpecProvider } from '@blocksuite/affine/shared/utils';
import {
AwarenessStore,
@@ -10,6 +9,7 @@ import {
type YBlock,
} from '@blocksuite/affine/store';
import { signal } from '@preact/signals-core';
import { Subject } from 'rxjs';
import { Awareness } from 'y-protocols/awareness.js';
import * as Y from 'yjs';
@@ -37,7 +37,7 @@ export class DocImpl implements Doc {
private readonly _historyObserver = () => {
this._updateCanUndoRedoSignals();
this.slots.historyUpdated.emit();
this.slots.historyUpdated.next();
};
private readonly _initSubDoc = () => {
@@ -65,7 +65,8 @@ export class DocImpl implements Doc {
private _loaded!: boolean;
private readonly _onLoadSlot = new Slot();
// eslint-disable-next-line rxjs/finnish
private readonly _onLoadSlot = new Subject();
/** Indicate whether the block tree is ready */
private _ready = false;
@@ -98,8 +99,10 @@ export class DocImpl implements Doc {
readonly rootDoc: Y.Doc;
readonly slots = {
historyUpdated: new Slot(),
yBlockUpdated: new Slot<
// eslint-disable-next-line rxjs/finnish
historyUpdated: new Subject<void>(),
// eslint-disable-next-line rxjs/finnish
yBlockUpdated: new Subject<
| {
type: 'add';
id: string;
@@ -170,11 +173,11 @@ export class DocImpl implements Doc {
}
private _handleYBlockAdd(id: string) {
this.slots.yBlockUpdated.emit({ type: 'add', id });
this.slots.yBlockUpdated.next({ type: 'add', id });
}
private _handleYBlockDelete(id: string) {
this.slots.yBlockUpdated.emit({ type: 'delete', id });
this.slots.yBlockUpdated.next({ type: 'delete', id });
}
private _handleYEvent(event: Y.YEvent<YBlock | Y.Text | Y.Array<unknown>>) {
@@ -229,13 +232,13 @@ export class DocImpl implements Doc {
private _destroy() {
this.awarenessStore.destroy();
this._ySpaceDoc.destroy();
this._onLoadSlot.dispose();
this._onLoadSlot.unsubscribe();
this._loaded = false;
}
dispose() {
this._destroy();
this.slots.historyUpdated.dispose();
this.slots.historyUpdated.unsubscribe();
if (this.ready) {
this._yBlocks.unobserveDeep(this._handleYEvents);
@@ -1,10 +1,10 @@
import { Slot } from '@blocksuite/affine/global/slot';
import {
createYProxy,
type DocMeta,
type DocsPropertiesMeta,
type WorkspaceMeta,
} from '@blocksuite/affine/store';
import { Subject } from 'rxjs';
import type * as Y from 'yjs';
type MetaState = {
@@ -15,10 +15,12 @@ type MetaState = {
};
export class WorkspaceMetaImpl implements WorkspaceMeta {
commonFieldsUpdated = new Slot();
docMetaAdded = new Slot<string>();
docMetaRemoved = new Slot<string>();
docMetaUpdated = new Slot();
/* eslint-disable rxjs/finnish */
commonFieldsUpdated = new Subject<void>();
docMetaAdded = new Subject<string>();
docMetaRemoved = new Subject<string>();
docMetaUpdated = new Subject<void>();
/* eslint-enable rxjs/finnish */
private readonly _handleDocCollectionMetaEvents = (
events: Y.YEvent<Y.Array<unknown> | Y.Text | Y.Map<unknown>>[]
@@ -81,7 +83,7 @@ export class WorkspaceMetaImpl implements WorkspaceMeta {
setProperties(meta: DocsPropertiesMeta) {
this._proxy.properties = meta;
this.docMetaUpdated.emit();
this.docMetaUpdated.next();
}
get docMetas() {
@@ -108,7 +110,7 @@ export class WorkspaceMetaImpl implements WorkspaceMeta {
}
private _handleCommonFieldsEvent() {
this.commonFieldsUpdated.emit();
this.commonFieldsUpdated.next();
}
private _handleDocMetaEvent() {
@@ -118,7 +120,7 @@ export class WorkspaceMetaImpl implements WorkspaceMeta {
docMetas.forEach(docMeta => {
if (!_prevDocs.has(docMeta.id)) {
this.docMetaAdded.emit(docMeta.id);
this.docMetaAdded.next(docMeta.id);
}
newDocs.add(docMeta.id);
});
@@ -126,13 +128,13 @@ export class WorkspaceMetaImpl implements WorkspaceMeta {
_prevDocs.forEach(prevDocId => {
const isRemoved = newDocs.has(prevDocId) === false;
if (isRemoved) {
this.docMetaRemoved.emit(prevDocId);
this.docMetaRemoved.next(prevDocId);
}
});
this._prevDocs = newDocs;
this.docMetaUpdated.emit();
this.docMetaUpdated.next();
}
addDocMeta(doc: DocMeta, index?: number) {
@@ -2,7 +2,6 @@ import {
BlockSuiteError,
ErrorCode,
} from '@blocksuite/affine/global/exceptions';
import { Slot } from '@blocksuite/affine/global/slot';
import { NoopLogger } from '@blocksuite/affine/global/utils';
import {
type CreateBlocksOptions,
@@ -19,6 +18,7 @@ import {
type BlobSource,
MemoryBlobSource,
} from '@blocksuite/affine/sync';
import { Subject } from 'rxjs';
import type { Awareness } from 'y-protocols/awareness.js';
import * as Y from 'yjs';
@@ -46,9 +46,11 @@ export class WorkspaceImpl implements Workspace {
meta: WorkspaceMeta;
slots = {
docListUpdated: new Slot(),
docRemoved: new Slot<string>(),
docCreated: new Slot<string>(),
/* eslint-disable rxjs/finnish */
docListUpdated: new Subject<void>(),
docRemoved: new Subject<string>(),
docCreated: new Subject<string>(),
/* eslint-enable rxjs/finnish */
};
get docs() {
@@ -82,7 +84,7 @@ export class WorkspaceImpl implements Workspace {
}
private _bindDocMetaEvents() {
this.meta.docMetaAdded.on(docId => {
this.meta.docMetaAdded.subscribe(docId => {
const doc = new DocImpl({
id: docId,
collection: this,
@@ -91,14 +93,14 @@ export class WorkspaceImpl implements Workspace {
this.blockCollections.set(doc.id, doc);
});
this.meta.docMetaUpdated.on(() => this.slots.docListUpdated.emit());
this.meta.docMetaUpdated.subscribe(() => this.slots.docListUpdated.next());
this.meta.docMetaRemoved.on(id => {
this.meta.docMetaRemoved.subscribe(id => {
const doc = this._getDoc(id);
if (!doc) return;
this.blockCollections.delete(id);
doc.remove();
this.slots.docRemoved.emit(id);
this.slots.docRemoved.next(id);
});
}
@@ -126,7 +128,7 @@ export class WorkspaceImpl implements Workspace {
createDate: Date.now(),
tags: [],
});
this.slots.docCreated.emit(docId);
this.slots.docCreated.next(docId);
return this.getDoc(docId, {
id: docId,
query,