diff --git a/blocksuite/affine/all/package.json b/blocksuite/affine/all/package.json index 22cb37d202..83691a1342 100644 --- a/blocksuite/affine/all/package.json +++ b/blocksuite/affine/all/package.json @@ -53,7 +53,8 @@ "@blocksuite/global": "workspace:*", "@blocksuite/inline": "workspace:*", "@blocksuite/store": "workspace:*", - "@blocksuite/sync": "workspace:*" + "@blocksuite/sync": "workspace:*", + "rxjs": "^7.8.1" }, "exports": { ".": "./src/index.ts", @@ -67,7 +68,7 @@ "./global/di": "./src/global/di.ts", "./global/types": "./src/global/types.ts", "./global/gfx": "./src/global/gfx.ts", - "./global/slot": "./src/global/slot.ts", + "./global/disposable": "./src/global/disposable.ts", "./global/lit": "./src/global/lit.ts", "./store": "./src/store/index.ts", "./store/test": "./src/store/test.ts", diff --git a/blocksuite/affine/all/src/global/disposable.ts b/blocksuite/affine/all/src/global/disposable.ts new file mode 100644 index 0000000000..5abe2b6a0f --- /dev/null +++ b/blocksuite/affine/all/src/global/disposable.ts @@ -0,0 +1 @@ +export * from '@blocksuite/global/disposable'; diff --git a/blocksuite/affine/all/src/global/slot.ts b/blocksuite/affine/all/src/global/slot.ts deleted file mode 100644 index 258a19a836..0000000000 --- a/blocksuite/affine/all/src/global/slot.ts +++ /dev/null @@ -1 +0,0 @@ -export * from '@blocksuite/global/slot'; diff --git a/blocksuite/affine/blocks/block-attachment/package.json b/blocksuite/affine/blocks/block-attachment/package.json index 686c48a8ba..e8b383363b 100644 --- a/blocksuite/affine/blocks/block-attachment/package.json +++ b/blocksuite/affine/blocks/block-attachment/package.json @@ -31,6 +31,7 @@ "file-type": "^20.0.0", "lit": "^3.2.0", "minimatch": "^10.0.1", + "rxjs": "^7.8.1", "zod": "^3.23.8" }, "exports": { diff --git a/blocksuite/affine/blocks/block-attachment/src/attachment-block.ts b/blocksuite/affine/blocks/block-attachment/src/attachment-block.ts index da9eef209c..220a7376f1 100644 --- a/blocksuite/affine/blocks/block-attachment/src/attachment-block.ts +++ b/blocksuite/affine/blocks/block-attachment/src/attachment-block.ts @@ -112,7 +112,7 @@ export class AttachmentBlockComponent extends CaptionedBlockComponent { + this.model.propsUpdated.subscribe(({ key }) => { if (key === 'sourceId') { // Reset the blob url when the sourceId is changed if (this.blobUrl) { diff --git a/blocksuite/affine/blocks/block-attachment/src/attachment-edgeless-block.ts b/blocksuite/affine/blocks/block-attachment/src/attachment-edgeless-block.ts index 71f857aa31..d9d3b1e8e9 100644 --- a/blocksuite/affine/blocks/block-attachment/src/attachment-edgeless-block.ts +++ b/blocksuite/affine/blocks/block-attachment/src/attachment-edgeless-block.ts @@ -22,14 +22,14 @@ export class AttachmentEdgelessBlockComponent extends toGfxBlockComponent( super.connectedCallback(); this._disposables.add( - this.slots.elementResizeStart.on(() => { + this.slots.elementResizeStart.subscribe(() => { this._isResizing = true; this._showOverlay = true; }) ); this._disposables.add( - this.slots.elementResizeEnd.on(() => { + this.slots.elementResizeEnd.subscribe(() => { this._isResizing = false; this._showOverlay = this._isResizing || this._isDragging || !this.selected$.peek(); diff --git a/blocksuite/affine/blocks/block-bookmark/package.json b/blocksuite/affine/blocks/block-bookmark/package.json index 93d3ee9201..c852c6f461 100644 --- a/blocksuite/affine/blocks/block-bookmark/package.json +++ b/blocksuite/affine/blocks/block-bookmark/package.json @@ -28,6 +28,7 @@ "@toeverything/theme": "^1.1.12", "lit": "^3.2.0", "minimatch": "^10.0.1", + "rxjs": "^7.8.1", "yjs": "^13.6.23", "zod": "^3.23.8" }, diff --git a/blocksuite/affine/blocks/block-bookmark/src/bookmark-block.ts b/blocksuite/affine/blocks/block-bookmark/src/bookmark-block.ts index 32eddf2a50..ff38946758 100644 --- a/blocksuite/affine/blocks/block-bookmark/src/bookmark-block.ts +++ b/blocksuite/affine/blocks/block-bookmark/src/bookmark-block.ts @@ -62,7 +62,7 @@ export class BookmarkBlockComponent extends CaptionedBlockComponent { + this.model.propsUpdated.subscribe(({ key }) => { if (key === 'url') { this.refreshData(); } diff --git a/blocksuite/affine/blocks/block-bookmark/src/components/bookmark-card.ts b/blocksuite/affine/blocks/block-bookmark/src/components/bookmark-card.ts index cca6df1854..05e15f3922 100644 --- a/blocksuite/affine/blocks/block-bookmark/src/components/bookmark-card.ts +++ b/blocksuite/affine/blocks/block-bookmark/src/components/bookmark-card.ts @@ -41,7 +41,7 @@ export class BookmarkCard extends WithDisposable(ShadowlessElement) { super.connectedCallback(); this.disposables.add( - this.bookmark.model.propsUpdated.on(() => { + this.bookmark.model.propsUpdated.subscribe(() => { this.requestUpdate(); }) ); diff --git a/blocksuite/affine/blocks/block-callout/package.json b/blocksuite/affine/blocks/block-callout/package.json index c0678def95..e6c70a9be2 100644 --- a/blocksuite/affine/blocks/block-callout/package.json +++ b/blocksuite/affine/blocks/block-callout/package.json @@ -32,6 +32,7 @@ "emoji-mart": "^5.6.0", "lit": "^3.2.0", "minimatch": "^10.0.1", + "rxjs": "^7.8.1", "zod": "^3.23.8" }, "exports": { diff --git a/blocksuite/affine/blocks/block-code/package.json b/blocksuite/affine/blocks/block-code/package.json index 5d4287bd23..561b4e5fd3 100644 --- a/blocksuite/affine/blocks/block-code/package.json +++ b/blocksuite/affine/blocks/block-code/package.json @@ -30,6 +30,7 @@ "@types/mdast": "^4.0.4", "lit": "^3.2.0", "minimatch": "^10.0.1", + "rxjs": "^7.8.1", "shiki": "^3.0.0", "zod": "^3.23.8" }, diff --git a/blocksuite/affine/blocks/block-code/src/clipboard/index.ts b/blocksuite/affine/blocks/block-code/src/clipboard/index.ts index efb60c1476..469e1a6332 100644 --- a/blocksuite/affine/blocks/block-code/src/clipboard/index.ts +++ b/blocksuite/affine/blocks/block-code/src/clipboard/index.ts @@ -14,7 +14,7 @@ import { Clipboard, type UIEventHandler, } from '@blocksuite/block-std'; -import { DisposableGroup } from '@blocksuite/global/slot'; +import { DisposableGroup } from '@blocksuite/global/disposable'; export class CodeClipboardController { private _clipboard!: Clipboard; diff --git a/blocksuite/affine/blocks/block-data-view/package.json b/blocksuite/affine/blocks/block-data-view/package.json index b341c03b17..ee3dadaebe 100644 --- a/blocksuite/affine/blocks/block-data-view/package.json +++ b/blocksuite/affine/blocks/block-data-view/package.json @@ -31,6 +31,7 @@ "@types/mdast": "^4.0.4", "lit": "^3.2.0", "minimatch": "^10.0.1", + "rxjs": "^7.8.1", "zod": "^3.23.8" }, "exports": { diff --git a/blocksuite/affine/blocks/block-data-view/src/block-meta/base.ts b/blocksuite/affine/blocks/block-data-view/src/block-meta/base.ts index 0d84493c7f..8dc164909c 100644 --- a/blocksuite/affine/blocks/block-data-view/src/block-meta/base.ts +++ b/blocksuite/affine/blocks/block-data-view/src/block-meta/base.ts @@ -1,5 +1,5 @@ import type { PropertyMetaConfig } from '@blocksuite/data-view'; -import type { Disposable } from '@blocksuite/global/slot'; +import type { DisposableMember } from '@blocksuite/global/disposable'; import type { Block, BlockModel } from '@blocksuite/store'; type PropertyMeta< @@ -14,7 +14,7 @@ type PropertyMeta< setColumnData?: (block: T, data: ColumnData) => void; get: (block: T) => Value; set?: (block: T, value: Value) => void; - updated: (block: T, callback: () => void) => Disposable; + updated: (block: T, callback: () => void) => DisposableMember; }; export type BlockMeta = { selector: (block: Block) => boolean; diff --git a/blocksuite/affine/blocks/block-data-view/src/block-meta/todo.ts b/blocksuite/affine/blocks/block-data-view/src/block-meta/todo.ts index 78f80ce181..d106a7da35 100644 --- a/blocksuite/affine/blocks/block-data-view/src/block-meta/todo.ts +++ b/blocksuite/affine/blocks/block-data-view/src/block-meta/todo.ts @@ -39,7 +39,7 @@ todoMeta.addProperty({ block.checked = value ?? false; }, updated: (block, callback) => { - return block.propsUpdated.on(({ key }) => { + return block.propsUpdated.subscribe(({ key }) => { if (key === 'checked') { callback(); } @@ -53,7 +53,7 @@ todoMeta.addProperty({ metaConfig: propertyPresets.textPropertyConfig, get: block => block.doc.meta?.title ?? '', updated: (block, callback) => { - return block.doc.workspace.slots.docListUpdated.on(() => { + return block.doc.workspace.slots.docListUpdated.subscribe(() => { callback(); }); }, diff --git a/blocksuite/affine/blocks/block-data-view/src/data-source.ts b/blocksuite/affine/blocks/block-data-view/src/data-source.ts index b5e0af22e4..b813b0d3d7 100644 --- a/blocksuite/affine/blocks/block-data-view/src/data-source.ts +++ b/blocksuite/affine/blocks/block-data-view/src/data-source.ts @@ -11,8 +11,8 @@ import type { EditorHost } from '@blocksuite/block-std'; import { DataSourceBase, type PropertyMetaConfig } from '@blocksuite/data-view'; import { propertyPresets } from '@blocksuite/data-view/property-presets'; import { BlockSuiteError } from '@blocksuite/global/exceptions'; -import { Slot } from '@blocksuite/global/slot'; import type { Block, Store } from '@blocksuite/store'; +import { Subject } from 'rxjs'; import type { BlockMeta } from './block-meta/base.js'; import { blockMetaMap } from './block-meta/index.js'; @@ -37,7 +37,7 @@ export class BlockQueryDataSource extends DataSourceBase { docDisposeMap = new Map void>(); slots = { - update: new Slot(), + update: new Subject(), }; private get blocks() { @@ -83,13 +83,13 @@ export class BlockQueryDataSource extends DataSourceBase { this.workspace.docs.forEach(doc => { this.listenToDoc(doc.getStore()); }); - this.workspace.slots.docCreated.on(id => { + this.workspace.slots.docCreated.subscribe(id => { const doc = this.workspace.getDoc(id); if (doc) { this.listenToDoc(doc); } }); - this.workspace.slots.docRemoved.on(id => { + this.workspace.slots.docRemoved.subscribe(id => { this.docDisposeMap.get(id)?.(); }); } @@ -149,7 +149,7 @@ export class BlockQueryDataSource extends DataSourceBase { listenToDoc(doc: Store) { this.docDisposeMap.set( doc.id, - doc.slots.blockUpdated.on(v => { + doc.slots.blockUpdated.subscribe(v => { if (v.type === 'add') { const blockById = doc.getBlock(v.id); if (blockById && this.meta.selector(blockById)) { @@ -158,8 +158,8 @@ export class BlockQueryDataSource extends DataSourceBase { } else if (v.type === 'delete') { this.blockMap.delete(v.id); } - this.slots.update.emit(); - }).dispose + this.slots.update.next(undefined); + }).unsubscribe ); } diff --git a/blocksuite/affine/blocks/block-database/package.json b/blocksuite/affine/blocks/block-database/package.json index 78e03420d2..d310e48803 100644 --- a/blocksuite/affine/blocks/block-database/package.json +++ b/blocksuite/affine/blocks/block-database/package.json @@ -34,6 +34,7 @@ "date-fns": "^4.0.0", "lit": "^3.2.0", "minimatch": "^10.0.1", + "rxjs": "^7.8.1", "yjs": "^13.6.21", "zod": "^3.23.8" }, diff --git a/blocksuite/affine/blocks/block-database/src/properties/link/cell-renderer.ts b/blocksuite/affine/blocks/block-database/src/properties/link/cell-renderer.ts index f5d7cbf4c2..de1bbde277 100644 --- a/blocksuite/affine/blocks/block-database/src/properties/link/cell-renderer.ts +++ b/blocksuite/affine/blocks/block-database/src/properties/link/cell-renderer.ts @@ -81,7 +81,7 @@ export class LinkCell extends BaseCellRenderer { return; } - std.getOptional(RefNodeSlotsProvider)?.docLinkClicked.emit({ + std.getOptional(RefNodeSlotsProvider)?.docLinkClicked.next({ pageId: this.docId$.value, host: std.host, }); diff --git a/blocksuite/affine/blocks/block-database/src/properties/rich-text/cell-renderer.ts b/blocksuite/affine/blocks/block-database/src/properties/rich-text/cell-renderer.ts index f21a9e7b8a..aa2ac45ab2 100644 --- a/blocksuite/affine/blocks/block-database/src/properties/rich-text/cell-renderer.ts +++ b/blocksuite/affine/blocks/block-database/src/properties/rich-text/cell-renderer.ts @@ -339,8 +339,10 @@ export class RichTextCell extends BaseCellRenderer { effect(() => { const editor = this.inlineEditor$.value; if (editor) { - const disposable = editor.slots.keydown.on(this._handleKeyDown); - return () => disposable.dispose(); + const disposable = editor.slots.keydown.subscribe( + this._handleKeyDown + ); + return () => disposable.unsubscribe(); } return; }) diff --git a/blocksuite/affine/blocks/block-divider/package.json b/blocksuite/affine/blocks/block-divider/package.json index ee7a7884c0..a3412b79a7 100644 --- a/blocksuite/affine/blocks/block-divider/package.json +++ b/blocksuite/affine/blocks/block-divider/package.json @@ -27,6 +27,7 @@ "@types/mdast": "^4.0.4", "lit": "^3.2.0", "minimatch": "^10.0.1", + "rxjs": "^7.8.1", "zod": "^3.23.8" }, "exports": { diff --git a/blocksuite/affine/blocks/block-edgeless-text/package.json b/blocksuite/affine/blocks/block-edgeless-text/package.json index ef4435c4da..7af65df2ca 100644 --- a/blocksuite/affine/blocks/block-edgeless-text/package.json +++ b/blocksuite/affine/blocks/block-edgeless-text/package.json @@ -29,6 +29,7 @@ "@toeverything/theme": "^1.1.12", "lit": "^3.2.0", "minimatch": "^10.0.1", + "rxjs": "^7.8.1", "zod": "^3.23.8" }, "exports": { diff --git a/blocksuite/affine/blocks/block-edgeless-text/src/commands/insert-edgeless-text.ts b/blocksuite/affine/blocks/block-edgeless-text/src/commands/insert-edgeless-text.ts index 8f07f29f70..98b6b42b7c 100644 --- a/blocksuite/affine/blocks/block-edgeless-text/src/commands/insert-edgeless-text.ts +++ b/blocksuite/affine/blocks/block-edgeless-text/src/commands/insert-edgeless-text.ts @@ -54,7 +54,7 @@ export const insertEdgelessTextCommand: Command< elements: [textId], editing: true, }); - const disposable = selection.slots.updated.on(() => { + const disposable = selection.slots.updated.subscribe(() => { const editing = selection.editing; const id = selection.selectedIds[0]; if (!editing || id !== textId) { @@ -63,7 +63,7 @@ export const insertEdgelessTextCommand: Command< textBlock.model.hasMaxWidth = true; } - disposable.dispose(); + disposable.unsubscribe(); } }); @@ -91,7 +91,8 @@ export const insertEdgelessTextCommand: Command< signal: abortController.signal, } ); - paragraph.model.deleted.once(() => { + const subscription = paragraph.model.deleted.subscribe(() => { + subscription.unsubscribe(); abortController.abort(); }); edgelessText.addEventListener( diff --git a/blocksuite/affine/blocks/block-edgeless-text/src/edgeless-text-block.ts b/blocksuite/affine/blocks/block-edgeless-text/src/edgeless-text-block.ts index 841b3fc35b..b0430887b4 100644 --- a/blocksuite/affine/blocks/block-edgeless-text/src/edgeless-text-block.ts +++ b/blocksuite/affine/blocks/block-edgeless-text/src/edgeless-text-block.ts @@ -92,7 +92,7 @@ export class EdgelessTextBlockComponent extends GfxBlockComponent { + this.model.propsUpdated.subscribe(({ key }) => { this.updateComplete .then(() => { const command = this.std.command; @@ -137,7 +137,7 @@ export class EdgelessTextBlockComponent extends GfxBlockComponent { + edgelessSelection.slots.updated.subscribe(() => { if (edgelessSelection.has(this.model.id) && edgelessSelection.editing) { this._editing = true; } else { diff --git a/blocksuite/affine/blocks/block-embed/package.json b/blocksuite/affine/blocks/block-embed/package.json index 81456722e9..998b342f5b 100644 --- a/blocksuite/affine/blocks/block-embed/package.json +++ b/blocksuite/affine/blocks/block-embed/package.json @@ -32,6 +32,7 @@ "lit": "^3.2.0", "lodash-es": "^4.17.21", "minimatch": "^10.0.1", + "rxjs": "^7.8.1", "yjs": "^13.6.21", "zod": "^3.23.8" }, diff --git a/blocksuite/affine/blocks/block-embed/src/common/render-linked-doc.ts b/blocksuite/affine/blocks/block-embed/src/common/render-linked-doc.ts index 7494df62b0..2f4e0b89ac 100644 --- a/blocksuite/affine/blocks/block-embed/src/common/render-linked-doc.ts +++ b/blocksuite/affine/blocks/block-embed/src/common/render-linked-doc.ts @@ -341,7 +341,7 @@ export function notifyDocCreated(std: BlockStdScope, doc: Store) { const clear = () => { doc.history.off('stack-item-added', addHandler); doc.history.off('stack-item-popped', popHandler); - disposable.dispose(); + disposable.unsubscribe(); }; const closeNotify = () => { abortController.abort(); @@ -353,7 +353,7 @@ export function notifyDocCreated(std: BlockStdScope, doc: Store) { const popHandler = doc.history.on('stack-item-popped', closeNotify); const disposable = std .get(EditorLifeCycleExtension) - .slots.unmounted.on(closeNotify); + .slots.unmounted.subscribe(closeNotify); notification.notify({ title: 'Linked doc created', diff --git a/blocksuite/affine/blocks/block-embed/src/common/to-edgeless-embed-block.ts b/blocksuite/affine/blocks/block-embed/src/common/to-edgeless-embed-block.ts index 58e7173688..f9d9ccd65b 100644 --- a/blocksuite/affine/blocks/block-embed/src/common/to-edgeless-embed-block.ts +++ b/blocksuite/affine/blocks/block-embed/src/common/to-edgeless-embed-block.ts @@ -54,14 +54,14 @@ export function toEdgelessEmbedBlock< super.connectedCallback(); this._disposables.add( - this.edgelessSlots.elementResizeStart.on(() => { + this.edgelessSlots.elementResizeStart.subscribe(() => { this._isResizing = true; this._showOverlay = true; }) ); this._disposables.add( - this.edgelessSlots.elementResizeEnd.on(() => { + this.edgelessSlots.elementResizeEnd.subscribe(() => { this._isResizing = false; this._showOverlay = this._isResizing || this._isDragging || !this.selected$.peek(); diff --git a/blocksuite/affine/blocks/block-embed/src/embed-figma-block/embed-figma-block.ts b/blocksuite/affine/blocks/block-embed/src/embed-figma-block/embed-figma-block.ts index c52d8be427..3bd6899646 100644 --- a/blocksuite/affine/blocks/block-embed/src/embed-figma-block/embed-figma-block.ts +++ b/blocksuite/affine/blocks/block-embed/src/embed-figma-block/embed-figma-block.ts @@ -62,7 +62,7 @@ export class EmbedFigmaBlockComponent extends EmbedBlockComponent { + this.model.propsUpdated.subscribe(({ key }) => { if (key === 'url') { this.refreshData(); } diff --git a/blocksuite/affine/blocks/block-embed/src/embed-github-block/embed-github-block.ts b/blocksuite/affine/blocks/block-embed/src/embed-github-block/embed-github-block.ts index cd5e9919d0..e38c6852b8 100644 --- a/blocksuite/affine/blocks/block-embed/src/embed-github-block/embed-github-block.ts +++ b/blocksuite/affine/blocks/block-embed/src/embed-github-block/embed-github-block.ts @@ -102,7 +102,7 @@ export class EmbedGithubBlockComponent extends EmbedBlockComponent< }); this.disposables.add( - this.model.propsUpdated.on(({ key }) => { + this.model.propsUpdated.subscribe(({ key }) => { if (key === 'url') { this.refreshData(); } diff --git a/blocksuite/affine/blocks/block-embed/src/embed-linked-doc-block/configs/slash-menu.ts b/blocksuite/affine/blocks/block-embed/src/embed-linked-doc-block/configs/slash-menu.ts index d510396256..18450d0fe9 100644 --- a/blocksuite/affine/blocks/block-embed/src/embed-linked-doc-block/configs/slash-menu.ts +++ b/blocksuite/affine/blocks/block-embed/src/embed-linked-doc-block/configs/slash-menu.ts @@ -73,12 +73,17 @@ const linkedDocSlashMenuConfig: SlashMenuConfig = { insertContent(std.host, model, triggerKey); const inlineEditor = getInlineEditorByModel(std.host, model); - // Wait for range to be updated - inlineEditor?.slots.inlineRangeSync.once(() => { - // TODO(@L-Sun): make linked-doc-widget as extension - // @ts-expect-error same as above - linkedDocWidget.show({ addTriggerKey: true }); - }); + if (inlineEditor) { + // Wait for range to be updated + const subscription = inlineEditor.slots.inlineRangeSync.subscribe( + () => { + // TODO(@L-Sun): make linked-doc-widget as extension + subscription.unsubscribe(); + // @ts-expect-error same as above + linkedDocWidget.show({ addTriggerKey: true }); + } + ); + } }, }, ], diff --git a/blocksuite/affine/blocks/block-embed/src/embed-linked-doc-block/embed-linked-doc-block.ts b/blocksuite/affine/blocks/block-embed/src/embed-linked-doc-block/embed-linked-doc-block.ts index 4cfe09968e..97142bde9e 100644 --- a/blocksuite/affine/blocks/block-embed/src/embed-linked-doc-block/embed-linked-doc-block.ts +++ b/blocksuite/affine/blocks/block-embed/src/embed-linked-doc-block/embed-linked-doc-block.ts @@ -87,7 +87,8 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent(resolve => { - linkedDoc.slots.rootAdded.once(() => { + const subscription = linkedDoc.slots.rootAdded.subscribe(() => { + subscription.unsubscribe(); resolve(); }); }); @@ -203,7 +204,7 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent { - this.std.getOptional(RefNodeSlotsProvider)?.docLinkClicked.emit({ + this.std.getOptional(RefNodeSlotsProvider)?.docLinkClicked.next({ ...this.referenceInfo$.peek(), openMode, event, @@ -285,7 +286,7 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent { + linkedDoc.workspace.slots.docListUpdated.subscribe(() => { this._load().catch(e => { console.error(e); this.isError = true; @@ -295,7 +296,7 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent { if ( payload.type === 'update' && @@ -318,7 +319,7 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent { + this.doc.workspace.slots.docListUpdated.subscribe(() => { this._setDocUpdatedAt(); }) ); @@ -337,7 +338,7 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent { + this.model.propsUpdated.subscribe(({ key }) => { if (key === 'style') { this._cardStyle = this.model.style; } diff --git a/blocksuite/affine/blocks/block-embed/src/embed-loom-block/embed-loom-block.ts b/blocksuite/affine/blocks/block-embed/src/embed-loom-block/embed-loom-block.ts index fc8e4ebf67..f29011446f 100644 --- a/blocksuite/affine/blocks/block-embed/src/embed-loom-block/embed-loom-block.ts +++ b/blocksuite/affine/blocks/block-embed/src/embed-loom-block/embed-loom-block.ts @@ -82,7 +82,7 @@ export class EmbedLoomBlockComponent extends EmbedBlockComponent< } this.disposables.add( - this.model.propsUpdated.on(({ key }) => { + this.model.propsUpdated.subscribe(({ key }) => { this.requestUpdate(); if (key === 'url') { this.refreshData(); diff --git a/blocksuite/affine/blocks/block-embed/src/embed-synced-doc-block/components/embed-synced-doc-card.ts b/blocksuite/affine/blocks/block-embed/src/embed-synced-doc-block/components/embed-synced-doc-card.ts index 322de08b83..aa4866b3b9 100644 --- a/blocksuite/affine/blocks/block-embed/src/embed-synced-doc-block/components/embed-synced-doc-card.ts +++ b/blocksuite/affine/blocks/block-embed/src/embed-synced-doc-block/components/embed-synced-doc-card.ts @@ -99,20 +99,21 @@ export class EmbedSyncedDocCard extends WithDisposable(ShadowlessElement) { if (syncedDoc.root) { renderLinkedDocInCard(this); } else { - syncedDoc.slots.rootAdded.once(() => { + const subscription = syncedDoc.slots.rootAdded.subscribe(() => { + subscription.unsubscribe(); renderLinkedDocInCard(this); }); } this.disposables.add( - syncedDoc.workspace.slots.docListUpdated.on(() => { + syncedDoc.workspace.slots.docListUpdated.subscribe(() => { renderLinkedDocInCard(this); }) ); // Should throttle the blockUpdated event to avoid too many re-renders // Because the blockUpdated event is triggered too frequently at some cases this.disposables.add( - syncedDoc.slots.blockUpdated.on( + syncedDoc.slots.blockUpdated.subscribe( throttle(payload => { if (this._dragging) { return; diff --git a/blocksuite/affine/blocks/block-embed/src/embed-synced-doc-block/embed-synced-doc-block.ts b/blocksuite/affine/blocks/block-embed/src/embed-synced-doc-block/embed-synced-doc-block.ts index abde2da18f..1e395314f2 100644 --- a/blocksuite/affine/blocks/block-embed/src/embed-synced-doc-block/embed-synced-doc-block.ts +++ b/blocksuite/affine/blocks/block-embed/src/embed-synced-doc-block/embed-synced-doc-block.ts @@ -129,7 +129,7 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent { + view.viewUpdated.subscribe(payload => { if ( payload.type !== 'block' || payload.view.model.flavour !== 'affine:embed-synced-doc' @@ -355,7 +355,7 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent { @@ -464,7 +464,10 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent(resolve => { - syncedDoc.slots.rootAdded.once(() => resolve()); + const subscription = syncedDoc.slots.rootAdded.subscribe(() => { + subscription.unsubscribe(); + resolve(); + }); }); } @@ -504,7 +507,7 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent { + this.model.propsUpdated.subscribe(({ key }) => { if (key === 'pageId' || key === 'style') { this._load().catch(e => { console.error(e); @@ -516,7 +519,7 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent { + this.doc.workspace.slots.docListUpdated.subscribe(() => { this._setDocUpdatedAt(); }) ); @@ -535,7 +538,7 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent { + this.syncedDoc.slots.blockUpdated.subscribe(() => { this._isEmptySyncedDoc = isEmptyDoc(this.syncedDoc, this.editorMode); }) ); diff --git a/blocksuite/affine/blocks/block-embed/src/embed-youtube-block/embed-youtube-block.ts b/blocksuite/affine/blocks/block-embed/src/embed-youtube-block/embed-youtube-block.ts index baec8260cc..5f1b00014c 100644 --- a/blocksuite/affine/blocks/block-embed/src/embed-youtube-block/embed-youtube-block.ts +++ b/blocksuite/affine/blocks/block-embed/src/embed-youtube-block/embed-youtube-block.ts @@ -85,7 +85,7 @@ export class EmbedYoutubeBlockComponent extends EmbedBlockComponent< } this.disposables.add( - this.model.propsUpdated.on(({ key }) => { + this.model.propsUpdated.subscribe(({ key }) => { this.requestUpdate(); if (key === 'url') { this.refreshData(); diff --git a/blocksuite/affine/blocks/block-frame/package.json b/blocksuite/affine/blocks/block-frame/package.json index 60fc702fbe..0a78e1cd46 100644 --- a/blocksuite/affine/blocks/block-frame/package.json +++ b/blocksuite/affine/blocks/block-frame/package.json @@ -28,6 +28,7 @@ "@types/mdast": "^4.0.4", "lit": "^3.2.0", "minimatch": "^10.0.1", + "rxjs": "^7.8.1", "yjs": "^13.6.21", "zod": "^3.23.8" }, diff --git a/blocksuite/affine/blocks/block-frame/src/frame-block.ts b/blocksuite/affine/blocks/block-frame/src/frame-block.ts index 2b914e7826..93c938a958 100644 --- a/blocksuite/affine/blocks/block-frame/src/frame-block.ts +++ b/blocksuite/affine/blocks/block-frame/src/frame-block.ts @@ -12,14 +12,14 @@ export class FrameBlockComponent extends GfxBlockComponent { super.connectedCallback(); this._disposables.add( - this.doc.slots.blockUpdated.on(({ type, id }) => { + this.doc.slots.blockUpdated.subscribe(({ type, id }) => { if (id === this.model.id && type === 'update') { this.requestUpdate(); } }) ); this._disposables.add( - this.gfx.viewport.viewportUpdated.on(() => { + this.gfx.viewport.viewportUpdated.subscribe(() => { this.requestUpdate(); }) ); diff --git a/blocksuite/affine/blocks/block-frame/src/frame-manager.ts b/blocksuite/affine/blocks/block-frame/src/frame-manager.ts index 929f079cfb..63c0579cde 100644 --- a/blocksuite/affine/blocks/block-frame/src/frame-manager.ts +++ b/blocksuite/affine/blocks/block-frame/src/frame-manager.ts @@ -13,6 +13,7 @@ import { isGfxGroupCompatibleModel, renderableInEdgeless, } from '@blocksuite/block-std/gfx'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; import { Bound, @@ -20,7 +21,6 @@ import { type IVec, type SerializedXYWH, } from '@blocksuite/global/gfx'; -import { DisposableGroup } from '@blocksuite/global/slot'; import { type BlockModel, Text } from '@blocksuite/store'; import * as Y from 'yjs'; @@ -98,11 +98,12 @@ export class FrameOverlay extends Overlay { if (highlightOutline) this._frame = frame; if (highlightElementsInBound) this._innerElements = innerElements; - this._disposable.add( - frame.deleted.once(() => { - this.clear(); - }) - ); + const subscription = frame.deleted.subscribe(() => { + subscription.unsubscribe(); + this.clear(); + }); + + this._disposable.add(subscription); this._renderer?.refresh(); } @@ -223,7 +224,7 @@ export class EdgelessFrameManager extends GfxExtension { const { surface: surfaceModel, doc } = this.gfx; this._disposable.add( - surfaceModel.elementAdded.on(({ id, local }) => { + surfaceModel.elementAdded.subscribe(({ id, local }) => { const element = surfaceModel.getElementById(id); if (element && local) { const frame = this.getFrameFromPoint(element.elementBound.center); @@ -249,7 +250,7 @@ export class EdgelessFrameManager extends GfxExtension { ); this._disposable.add( - doc.slots.blockUpdated.on(payload => { + doc.slots.blockUpdated.subscribe(payload => { if ( payload.type === 'add' && payload.model instanceof GfxBlockElementModel && diff --git a/blocksuite/affine/blocks/block-image/package.json b/blocksuite/affine/blocks/block-image/package.json index 7ef9c19d67..711a269e39 100644 --- a/blocksuite/affine/blocks/block-image/package.json +++ b/blocksuite/affine/blocks/block-image/package.json @@ -31,6 +31,7 @@ "file-type": "^20.0.0", "lit": "^3.2.0", "minimatch": "^10.0.1", + "rxjs": "^7.8.1", "zod": "^3.23.8" }, "exports": { diff --git a/blocksuite/affine/blocks/block-image/src/components/page-image-block.ts b/blocksuite/affine/blocks/block-image/src/components/page-image-block.ts index fb1a81a47f..e8fe769110 100644 --- a/blocksuite/affine/blocks/block-image/src/components/page-image-block.ts +++ b/blocksuite/affine/blocks/block-image/src/components/page-image-block.ts @@ -191,7 +191,7 @@ export class ImageBlockPageComponent extends WithDisposable(ShadowlessElement) { private _handleSelection() { const selection = this._host.selection; this._disposables.add( - selection.slots.changed.on(selList => { + selection.slots.changed.subscribe(selList => { this._isSelected = selList.some( sel => sel.blockId === this.block.blockId && sel.is(ImageSelection) ); @@ -199,7 +199,7 @@ export class ImageBlockPageComponent extends WithDisposable(ShadowlessElement) { ); this._disposables.add( - this._model.propsUpdated.on(() => { + this._model.propsUpdated.subscribe(() => { this.requestUpdate(); }) ); diff --git a/blocksuite/affine/blocks/block-image/src/image-block.ts b/blocksuite/affine/blocks/block-image/src/image-block.ts index 90f55bf43c..3455221a5d 100644 --- a/blocksuite/affine/blocks/block-image/src/image-block.ts +++ b/blocksuite/affine/blocks/block-image/src/image-block.ts @@ -60,7 +60,7 @@ export class ImageBlockComponent extends CaptionedBlockComponent { + this.model.propsUpdated.subscribe(({ key }) => { if (key === 'sourceId') { this.refreshData(); } diff --git a/blocksuite/affine/blocks/block-image/src/image-edgeless-block.ts b/blocksuite/affine/blocks/block-image/src/image-edgeless-block.ts index 9cd53082dd..19cee0cae6 100644 --- a/blocksuite/affine/blocks/block-image/src/image-edgeless-block.ts +++ b/blocksuite/affine/blocks/block-image/src/image-edgeless-block.ts @@ -62,7 +62,7 @@ export class ImageEdgelessBlockComponent extends GfxBlockComponent { + this.model.propsUpdated.subscribe(({ key }) => { if (key === 'sourceId') { this.refreshData(); } diff --git a/blocksuite/affine/blocks/block-latex/package.json b/blocksuite/affine/blocks/block-latex/package.json index bacad3a7cd..b69ecc38e8 100644 --- a/blocksuite/affine/blocks/block-latex/package.json +++ b/blocksuite/affine/blocks/block-latex/package.json @@ -34,6 +34,7 @@ "lit": "^3.2.0", "minimatch": "^10.0.1", "remark-math": "^6.0.0", + "rxjs": "^7.8.1", "zod": "^3.23.8" }, "exports": { diff --git a/blocksuite/affine/blocks/block-list/package.json b/blocksuite/affine/blocks/block-list/package.json index 8e989445f2..1c12401876 100644 --- a/blocksuite/affine/blocks/block-list/package.json +++ b/blocksuite/affine/blocks/block-list/package.json @@ -29,6 +29,7 @@ "@types/mdast": "^4.0.4", "lit": "^3.2.0", "minimatch": "^10.0.1", + "rxjs": "^7.8.1", "zod": "^3.23.8" }, "devDependencies": { diff --git a/blocksuite/affine/blocks/block-note/package.json b/blocksuite/affine/blocks/block-note/package.json index 13c3bf967c..a9241ceb74 100644 --- a/blocksuite/affine/blocks/block-note/package.json +++ b/blocksuite/affine/blocks/block-note/package.json @@ -33,6 +33,7 @@ "@vanilla-extract/css": "^1.17.0", "lit": "^3.2.0", "minimatch": "^10.0.1", + "rxjs": "^7.8.1", "zod": "^3.23.8" }, "exports": { diff --git a/blocksuite/affine/blocks/block-note/src/note-edgeless-block.ts b/blocksuite/affine/blocks/block-note/src/note-edgeless-block.ts index d0fb614772..a2381276b4 100644 --- a/blocksuite/affine/blocks/block-note/src/note-edgeless-block.ts +++ b/blocksuite/affine/blocks/block-note/src/note-edgeless-block.ts @@ -126,7 +126,7 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent( this._editing = selection.has(this.model.id) && selection.editing; this._disposables.add( - selection.slots.updated.on(() => { + selection.slots.updated.subscribe(() => { if (selection.has(this.model.id) && selection.editing) { this._editing = true; } else { @@ -147,7 +147,7 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent( const selection = this.gfx.selection; _disposables.add( - this.edgelessSlots.elementResizeStart.on(() => { + this.edgelessSlots.elementResizeStart.subscribe(() => { if (selection.selectedElements.includes(this.model)) { this._isResizing = true; } @@ -155,7 +155,7 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent( ); _disposables.add( - this.edgelessSlots.elementResizeEnd.on(() => { + this.edgelessSlots.elementResizeEnd.subscribe(() => { this._isResizing = false; }) ); diff --git a/blocksuite/affine/blocks/block-paragraph/package.json b/blocksuite/affine/blocks/block-paragraph/package.json index 6a24fcd58b..57b0bb56dc 100644 --- a/blocksuite/affine/blocks/block-paragraph/package.json +++ b/blocksuite/affine/blocks/block-paragraph/package.json @@ -28,6 +28,7 @@ "@types/mdast": "^4.0.4", "lit": "^3.2.0", "minimatch": "^10.0.1", + "rxjs": "^7.8.1", "zod": "^3.23.8" }, "exports": { diff --git a/blocksuite/affine/blocks/block-root/package.json b/blocksuite/affine/blocks/block-root/package.json index f85ed27c93..7b673a953b 100644 --- a/blocksuite/affine/blocks/block-root/package.json +++ b/blocksuite/affine/blocks/block-root/package.json @@ -60,6 +60,7 @@ "lit": "^3.2.0", "lodash-es": "^4.17.21", "minimatch": "^10.0.1", + "rxjs": "^7.8.1", "simple-xml-to-json": "^1.2.2", "yjs": "^13.6.21", "zod": "^3.23.8" diff --git a/blocksuite/affine/blocks/block-root/src/clipboard/page-clipboard.ts b/blocksuite/affine/blocks/block-root/src/clipboard/page-clipboard.ts index 3119ab2b0e..acbb721fd1 100644 --- a/blocksuite/affine/blocks/block-root/src/clipboard/page-clipboard.ts +++ b/blocksuite/affine/blocks/block-root/src/clipboard/page-clipboard.ts @@ -15,7 +15,7 @@ import { retainFirstModelCommand, } from '@blocksuite/affine-shared/commands'; import type { UIEventHandler } from '@blocksuite/block-std'; -import { DisposableGroup } from '@blocksuite/global/slot'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import type { BlockSnapshot, Store } from '@blocksuite/store'; import { ReadOnlyClipboard } from './readonly-clipboard'; diff --git a/blocksuite/affine/blocks/block-root/src/clipboard/readonly-clipboard.ts b/blocksuite/affine/blocks/block-root/src/clipboard/readonly-clipboard.ts index 862346e4d6..e69da3daaf 100644 --- a/blocksuite/affine/blocks/block-root/src/clipboard/readonly-clipboard.ts +++ b/blocksuite/affine/blocks/block-root/src/clipboard/readonly-clipboard.ts @@ -14,7 +14,7 @@ import { getSelectedModelsCommand, } from '@blocksuite/affine-shared/commands'; import type { BlockComponent, UIEventHandler } from '@blocksuite/block-std'; -import { DisposableGroup } from '@blocksuite/global/slot'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { ClipboardAdapter } from './adapter.js'; diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/clipboard/clipboard.ts b/blocksuite/affine/blocks/block-root/src/edgeless/clipboard/clipboard.ts index 9956fae928..e879f3e0e1 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/clipboard/clipboard.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/clipboard/clipboard.ts @@ -48,6 +48,7 @@ import { type SerializedElement, SortOrder, } from '@blocksuite/block-std/gfx'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; import { Bound, @@ -57,7 +58,6 @@ import { type SerializedXYWH, Vec, } from '@blocksuite/global/gfx'; -import { DisposableGroup } from '@blocksuite/global/slot'; import { assertType } from '@blocksuite/global/utils'; import { type BlockSnapshot, diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/auto-complete/auto-complete-panel.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/auto-complete/auto-complete-panel.ts index 7adcbc306b..14e8da6ca1 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/auto-complete/auto-complete-panel.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/components/auto-complete/auto-complete-panel.ts @@ -568,7 +568,7 @@ export class EdgelessAutoCompletePanel extends WithDisposable(LitElement) { override firstUpdated() { this.disposables.add( - this.edgeless.service.viewport.viewportUpdated.on(() => + this.edgeless.service.viewport.viewportUpdated.subscribe(() => this.requestUpdate() ) ); diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/auto-complete/edgeless-auto-complete.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/auto-complete/edgeless-auto-complete.ts index 38882a7479..5efd92f70f 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/auto-complete/edgeless-auto-complete.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/components/auto-complete/edgeless-auto-complete.ts @@ -25,10 +25,10 @@ import { import { handleNativeRangeAtPoint } from '@blocksuite/affine-shared/utils'; import { type BlockStdScope, stdContext } from '@blocksuite/block-std'; import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import type { Bound, IVec } from '@blocksuite/global/gfx'; import { Vec } from '@blocksuite/global/gfx'; import { WithDisposable } from '@blocksuite/global/lit'; -import { DisposableGroup } from '@blocksuite/global/slot'; import { ArrowUpBigIcon, PlusIcon, @@ -670,7 +670,7 @@ export class EdgelessAutoComplete extends WithDisposable(LitElement) { const { _disposables, edgeless } = this; _disposables.add( - this.gfx.selection.slots.updated.on(() => { + this.gfx.selection.slots.updated.subscribe(() => { this._autoCompleteOverlay.linePoints = []; this._autoCompleteOverlay.renderShape = null; }) diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/connector/connector-handle.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/connector/connector-handle.ts index 632a5265cc..2e31bbe373 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/connector/connector-handle.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/components/connector/connector-handle.ts @@ -9,9 +9,9 @@ import { stdContext, } from '@blocksuite/block-std'; import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { Vec } from '@blocksuite/global/gfx'; import { WithDisposable } from '@blocksuite/global/lit'; -import { DisposableGroup } from '@blocksuite/global/slot'; import type { Store } from '@blocksuite/store'; import { consume } from '@lit/context'; import { css, html, LitElement } from 'lit'; @@ -63,11 +63,11 @@ export class EdgelessConnectorHandle extends WithDisposable(LitElement) { const edgeless = this.edgeless; this._disposables.addFromEvent(this._startHandler, 'pointerdown', e => { - edgeless.slots.elementResizeStart.emit(); + edgeless.slots.elementResizeStart.next(); this._capPointerDown(e, 'source'); }); this._disposables.addFromEvent(this._endHandler, 'pointerdown', e => { - edgeless.slots.elementResizeStart.emit(); + edgeless.slots.elementResizeStart.next(); this._capPointerDown(e, 'target'); }); this._disposables.add(() => { @@ -96,7 +96,7 @@ export class EdgelessConnectorHandle extends WithDisposable(LitElement) { _disposables.dispose(); this._disposables = new DisposableGroup(); this._bindEvent(); - edgeless.slots.elementResizeEnd.emit(); + edgeless.slots.elementResizeEnd.next(); }); } @@ -105,7 +105,7 @@ export class EdgelessConnectorHandle extends WithDisposable(LitElement) { const { viewport } = edgeless.service; this._lastZoom = viewport.zoom; - edgeless.service.viewport.viewportUpdated.on(() => { + edgeless.service.viewport.viewportUpdated.subscribe(() => { if (viewport.zoom !== this._lastZoom) { this._lastZoom = viewport.zoom; this.requestUpdate(); diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/note-slicer/index.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/note-slicer/index.ts index cd6477fc13..a3a08e772a 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/note-slicer/index.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/components/note-slicer/index.ts @@ -10,8 +10,8 @@ import { TelemetryProvider } from '@blocksuite/affine-shared/services'; import { getRectByBlockComponent } from '@blocksuite/affine-shared/utils'; import { WidgetComponent } from '@blocksuite/block-std'; import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { deserializeXYWH, Point, serializeXYWH } from '@blocksuite/global/gfx'; -import { DisposableGroup } from '@blocksuite/global/slot'; import { ScissorsIcon } from '@blocksuite/icons/lit'; import { css, html, nothing, type PropertyValues } from 'lit'; import { state } from 'lit/decorators.js'; @@ -267,13 +267,13 @@ export class NoteSlicer extends WidgetComponent< this._updateDivingLineAndBlockIds(); disposables.add( - block.slots.elementResizeStart.on(() => { + block.slots.elementResizeStart.subscribe(() => { this._isResizing = true; }) ); disposables.add( - block.slots.elementResizeEnd.on(() => { + block.slots.elementResizeEnd.subscribe(() => { this._isResizing = false; }) ); @@ -289,14 +289,14 @@ export class NoteSlicer extends WidgetComponent< ); disposables.add( - gfx.viewport.viewportUpdated.on(() => { + gfx.viewport.viewportUpdated.subscribe(() => { this._hidden = true; this.requestUpdate(); }) ); disposables.add( - gfx.selection.slots.updated.on(() => { + gfx.selection.slots.updated.subscribe(() => { this._enableNoteSlicer = false; this._updateSlicedNote(); @@ -307,7 +307,7 @@ export class NoteSlicer extends WidgetComponent< ); disposables.add( - block.slots.toggleNoteSlicer.on(() => { + block.slots.toggleNoteSlicer.subscribe(() => { this._enableNoteSlicer = !this._enableNoteSlicer; if (this.selectedRectEle && this._enableNoteSlicer) { @@ -411,7 +411,7 @@ export class NoteSlicer extends WidgetComponent< if (this._anchorNote) { this._noteDisposables = new DisposableGroup(); this._noteDisposables.add( - this._anchorNote.propsUpdated.on(({ key }) => { + this._anchorNote.propsUpdated.subscribe(({ key }) => { if (key === 'children' || key === 'xywh') { this.requestUpdate(); } diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/panel/shape-panel.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/panel/shape-panel.ts index 8617770417..62b9d35bfc 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/panel/shape-panel.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/components/panel/shape-panel.ts @@ -1,8 +1,8 @@ import { ShapeStyle } from '@blocksuite/affine-model'; -import { Slot } from '@blocksuite/global/slot'; import { css, html, LitElement } from 'lit'; import { property } from 'lit/decorators.js'; import { repeat } from 'lit/directives/repeat.js'; +import { Subject } from 'rxjs'; import type { ShapeTool } from '../../gfx-tool/shape-tool.js'; import { ShapeComponentConfig } from '../toolbar/shape/shape-menu-config.js'; @@ -18,16 +18,16 @@ export class EdgelessShapePanel extends LitElement { `; slots = { - select: new Slot(), + select: new Subject(), }; private _onSelect(value: ShapeTool['activatedOption']['shapeName']) { this.selectedShape = value; - this.slots.select.emit(value); + this.slots.select.next(value); } override disconnectedCallback(): void { - this.slots.select.dispose(); + this.slots.select.complete(); super.disconnectedCallback(); } diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/rects/edgeless-selected-rect.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/rects/edgeless-selected-rect.ts index d686f372bd..1a59871229 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/rects/edgeless-selected-rect.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/components/rects/edgeless-selected-rect.ts @@ -55,13 +55,13 @@ import { deserializeXYWH, normalizeDegAngle, } from '@blocksuite/global/gfx'; -import { type Disposable, Slot } from '@blocksuite/global/slot'; import { assertType } from '@blocksuite/global/utils'; import { css, html, nothing } from 'lit'; import { state } from 'lit/decorators.js'; import { ifDefined } from 'lit/directives/if-defined.js'; import { styleMap } from 'lit/directives/style-map.js'; import clamp from 'lodash-es/clamp'; +import { Subject, type Subscription } from 'rxjs'; import type { EdgelessRootBlockComponent } from '../../edgeless-root-block.js'; import { @@ -447,13 +447,13 @@ export class EdgelessSelectedRectWidget extends WidgetComponent< private _dragEndCallback: (() => void)[] = []; private readonly _initSelectedSlot = () => { - this._propDisposables.forEach(disposable => disposable.dispose()); + this._propDisposables.forEach(disposable => disposable.unsubscribe()); this._propDisposables = []; this.selection.selectedElements.forEach(element => { if ('flavour' in element) { this._propDisposables.push( - element.propsUpdated.on(() => { + element.propsUpdated.subscribe(() => { this._updateOnElementChange(element.id); }) ); @@ -462,7 +462,7 @@ export class EdgelessSelectedRectWidget extends WidgetComponent< }; private readonly _onDragEnd = () => { - this.slots.dragEnd.emit(); + this.slots.dragEnd.next(); this.doc.transact(() => { this._dragEndCallback.forEach(cb => cb()); @@ -478,7 +478,7 @@ export class EdgelessSelectedRectWidget extends WidgetComponent< this._scaleDirection = undefined; this._updateMode(); - this.block.slots.elementResizeEnd.emit(); + this.block.slots.elementResizeEnd.next(); this.frameOverlay.clear(); }; @@ -494,7 +494,7 @@ export class EdgelessSelectedRectWidget extends WidgetComponent< >, direction: HandleDirection ) => { - this.slots.dragMove.emit(); + this.slots.dragMove.next(); const { gfx } = this; @@ -557,7 +557,7 @@ export class EdgelessSelectedRectWidget extends WidgetComponent< }; private readonly _onDragRotate = (center: IPoint, delta: number) => { - this.slots.dragRotate.emit(); + this.slots.dragRotate.next(); const { selection } = this; const m = new DOMMatrix() @@ -602,12 +602,12 @@ export class EdgelessSelectedRectWidget extends WidgetComponent< }; private readonly _onDragStart = () => { - this.slots.dragStart.emit(); + this.slots.dragStart.next(); const rotation = this._resizeManager.rotation; this._dragEndCallback = []; - this.block.slots.elementResizeStart.emit(); + this.block.slots.elementResizeStart.next(); this.selection.selectedElements.forEach(el => { el.stash('xywh'); @@ -644,7 +644,7 @@ export class EdgelessSelectedRectWidget extends WidgetComponent< this._updateResizeManagerState(true); }; - private _propDisposables: Disposable[] = []; + private _propDisposables: Subscription[] = []; private readonly _resizeManager: HandleResizeManager; @@ -836,10 +836,10 @@ export class EdgelessSelectedRectWidget extends WidgetComponent< }, this); readonly slots = { - dragStart: new Slot(), - dragMove: new Slot(), - dragRotate: new Slot(), - dragEnd: new Slot(), + dragStart: new Subject(), + dragMove: new Subject(), + dragRotate: new Subject(), + dragEnd: new Subject(), }; get dragDirection() { @@ -1307,39 +1307,41 @@ export class EdgelessSelectedRectWidget extends WidgetComponent< _disposables.add( // viewport zooming / scrolling - gfx.viewport.viewportUpdated.on(this._updateOnViewportChange) + gfx.viewport.viewportUpdated.subscribe(this._updateOnViewportChange) ); if (gfx.surface) { _disposables.add( - gfx.surface.elementAdded.on(this._updateOnElementChange) + gfx.surface.elementAdded.subscribe(this._updateOnElementChange) ); _disposables.add( - gfx.surface.elementRemoved.on(this._updateOnElementChange) + gfx.surface.elementRemoved.subscribe(this._updateOnElementChange) ); _disposables.add( - gfx.surface.elementUpdated.on(this._updateOnElementChange) + gfx.surface.elementUpdated.subscribe(this._updateOnElementChange) ); } _disposables.add( - this.doc.slots.blockUpdated.on(this._updateOnElementChange) - ); - - _disposables.add(selection.slots.updated.on(this._updateOnSelectionChange)); - - _disposables.add( - block.slots.readonlyUpdated.on(() => this.requestUpdate()) + this.doc.slots.blockUpdated.subscribe(this._updateOnElementChange) ); _disposables.add( - block.slots.elementResizeStart.on(() => (this._isResizing = true)) + selection.slots.updated.subscribe(this._updateOnSelectionChange) + ); + + _disposables.add( + block.slots.readonlyUpdated.subscribe(() => this.requestUpdate()) + ); + + _disposables.add( + block.slots.elementResizeStart.subscribe(() => (this._isResizing = true)) ); _disposables.add( - block.slots.elementResizeEnd.on(() => (this._isResizing = false)) + block.slots.elementResizeEnd.subscribe(() => (this._isResizing = false)) ); _disposables.add(() => { - this._propDisposables.forEach(disposable => disposable.dispose()); + this._propDisposables.forEach(disposable => disposable.unsubscribe()); }); this.block.handleEvent( diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/text/edgeless-connector-label-editor.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/text/edgeless-connector-label-editor.ts index 45aa011dcc..9419cc067a 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/text/edgeless-connector-label-editor.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/components/text/edgeless-connector-label-editor.ts @@ -127,7 +127,7 @@ export class EdgelessConnectorLabelEditor extends WithDisposable( if (!this.inlineEditor) return; this.inlineEditor.selectAll(); - this.inlineEditor.slots.renderComplete.on(() => { + this.inlineEditor.slots.renderComplete.subscribe(() => { this.requestUpdate(); }); @@ -153,13 +153,13 @@ export class EdgelessConnectorLabelEditor extends WithDisposable( ); this.disposables.add( - edgeless.service.surface.elementUpdated.on(({ id }) => { + edgeless.service.surface.elementUpdated.subscribe(({ id }) => { if (id === connector.id) this.requestUpdate(); }) ); this.disposables.add( - edgeless.service.viewport.viewportUpdated.on(() => { + edgeless.service.viewport.viewportUpdated.subscribe(() => { this.requestUpdate(); }) ); diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/text/edgeless-frame-title-editor.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/text/edgeless-frame-title-editor.ts index 96f4b531f2..a3f9efac1f 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/text/edgeless-frame-title-editor.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/components/text/edgeless-frame-title-editor.ts @@ -69,7 +69,7 @@ export class EdgelessFrameTitleEditor extends WithDisposable( this.inlineEditor.selectAll(); - this.inlineEditor.slots.renderComplete.on(() => { + this.inlineEditor.slots.renderComplete.subscribe(() => { this.requestUpdate(); }); @@ -87,7 +87,7 @@ export class EdgelessFrameTitleEditor extends WithDisposable( }) ); this.disposables.add( - this.edgeless.service.viewport.viewportUpdated.on(() => { + this.edgeless.service.viewport.viewportUpdated.subscribe(() => { this.requestUpdate(); }) ); diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/text/edgeless-group-title-editor.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/text/edgeless-group-title-editor.ts index 36218b3ae8..fb1e21bf20 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/text/edgeless-group-title-editor.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/components/text/edgeless-group-title-editor.ts @@ -54,7 +54,7 @@ export class EdgelessGroupTitleEditor extends WithDisposable( this.group.showTitle = false; - this.inlineEditor.slots.renderComplete.on(() => { + this.inlineEditor.slots.renderComplete.subscribe(() => { this.requestUpdate(); }); @@ -72,7 +72,7 @@ export class EdgelessGroupTitleEditor extends WithDisposable( }) ); this.disposables.add( - this.edgeless.service.viewport.viewportUpdated.on(() => { + this.edgeless.service.viewport.viewportUpdated.subscribe(() => { this.requestUpdate(); }) ); diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/text/edgeless-shape-text-editor.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/text/edgeless-shape-text-editor.ts index 20a5350d7d..a8679b3c8b 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/text/edgeless-shape-text-editor.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/components/text/edgeless-shape-text-editor.ts @@ -178,7 +178,7 @@ export class EdgelessShapeTextEditor extends WithDisposable(ShadowlessElement) { this.element.textDisplay = false; this.disposables.add( - this.edgeless.service.viewport.viewportUpdated.on(() => { + this.edgeless.service.viewport.viewportUpdated.subscribe(() => { this.requestUpdate(); this.updateComplete .then(() => { @@ -208,7 +208,7 @@ export class EdgelessShapeTextEditor extends WithDisposable(ShadowlessElement) { } this.disposables.add( - this.inlineEditor.slots.renderComplete.on(() => { + this.inlineEditor.slots.renderComplete.subscribe(() => { this._updateElementWH(); }) ); diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/common/draggable/draggable-element.controller.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/common/draggable/draggable-element.controller.ts index 60a3a20c44..883a057bf6 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/common/draggable/draggable-element.controller.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/common/draggable/draggable-element.controller.ts @@ -386,7 +386,7 @@ export class EdgelessDraggableElementController hostConnected() { this.host.disposables.add( - this.options.service.viewport.viewportUpdated.on(({ zoom }) => { + this.options.service.viewport.viewportUpdated.subscribe(({ zoom }) => { this._updateOverlayScale(zoom); }) ); diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/common/slide-menu.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/common/slide-menu.ts index f7ae613475..6851d63b9e 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/common/slide-menu.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/common/slide-menu.ts @@ -121,7 +121,7 @@ export class EdgelessSlideMenu extends WithDisposable(LitElement) { this._toggleSlideButton(); }); this._disposables.add( - this.toolbarSlots.resize.on(() => this._toggleSlideButton()) + this.toolbarSlots.resize.subscribe(() => this._toggleSlideButton()) ); } diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/context.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/context.ts index c78760ca9d..81e6e40cbc 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/context.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/context.ts @@ -1,11 +1,11 @@ import type { ColorScheme } from '@blocksuite/affine-model'; -import type { Slot } from '@blocksuite/global/slot'; import { createContext } from '@lit/context'; +import type { Subject } from 'rxjs'; import type { EdgelessToolbarWidget } from './edgeless-toolbar.js'; export interface EdgelessToolbarSlots { - resize: Slot<{ w: number; h: number }>; + resize: Subject<{ w: number; h: number }>; } export const edgelessToolbarSlotsContext = createContext( diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/edgeless-toolbar.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/edgeless-toolbar.ts index 5e7b4c807d..4838c96bec 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/edgeless-toolbar.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/edgeless-toolbar.ts @@ -16,7 +16,6 @@ import { import { stopPropagation } from '@blocksuite/affine-shared/utils'; import { WidgetComponent } from '@blocksuite/block-std'; import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx'; -import { Slot } from '@blocksuite/global/slot'; import { ArrowLeftSmallIcon, ArrowRightSmallIcon, @@ -30,6 +29,7 @@ import { css, html, nothing, unsafeCSS } from 'lit'; import { query, state } from 'lit/decorators.js'; import { cache } from 'lit/directives/cache.js'; import debounce from 'lodash-es/debounce'; +import { Subject } from 'rxjs'; import type { EdgelessRootBlockComponent } from '../../edgeless-root-block.js'; import type { MenuPopper } from './common/create-popper.js'; @@ -238,7 +238,7 @@ export class EdgelessToolbarWidget extends WidgetComponent< ({ w }: { w: number }) => { if (!this.isConnected) return; - this.slots.resize.emit({ w, h: TOOLBAR_HEIGHT }); + this.slots.resize.next({ w, h: TOOLBAR_HEIGHT }); this.containerWidth = w; if (this._denseSeniorTools) { @@ -273,7 +273,7 @@ export class EdgelessToolbarWidget extends WidgetComponent< private readonly _slotsProvider = new ContextProvider(this, { context: edgelessToolbarSlotsContext, - initialValue: { resize: new Slot() } satisfies EdgelessToolbarSlots, + initialValue: { resize: new Subject() } satisfies EdgelessToolbarSlots, }); private readonly _themeProvider = new ContextProvider(this, { @@ -605,22 +605,22 @@ export class EdgelessToolbarWidget extends WidgetComponent< const { _disposables, block, gfx } = this; _disposables.add( - gfx.viewport.viewportUpdated.on(() => this.requestUpdate()) + gfx.viewport.viewportUpdated.subscribe(() => this.requestUpdate()) ); _disposables.add( - block.slots.readonlyUpdated.on(() => { + block.slots.readonlyUpdated.subscribe(() => { this.requestUpdate(); }) ); _disposables.add( - block.slots.toolbarLocked.on(disabled => { + block.slots.toolbarLocked.subscribe(disabled => { this.toggleAttribute('disabled', disabled); }) ); // This state from `editPropsStore` is not reactive, // if the value is updated outside of this component, it will not be reflected. _disposables.add( - this.std.get(EditPropsStore).slots.storageUpdated.on(({ key }) => { + this.std.get(EditPropsStore).slots.storageUpdated.subscribe(({ key }) => { if (key === 'presentHideToolbar') { this.requestUpdate(); } diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/present/frame-order-menu.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/present/frame-order-menu.ts index 72fc79cf09..e72eda1ba4 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/present/frame-order-menu.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/present/frame-order-menu.ts @@ -1,7 +1,7 @@ import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface'; import { generateKeyBetweenV2 } from '@blocksuite/block-std/gfx'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { SignalWatcher, WithDisposable } from '@blocksuite/global/lit'; -import { DisposableGroup } from '@blocksuite/global/slot'; import { css, html, LitElement, nothing } from 'lit'; import { property, query, state } from 'lit/decorators.js'; import { repeat } from 'lit/directives/repeat.js'; diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/present/navigator-setting-button.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/present/navigator-setting-button.ts index 313c468085..7cf43d0a6a 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/present/navigator-setting-button.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/present/navigator-setting-button.ts @@ -73,7 +73,7 @@ export class EdgelessNavigatorSettingButton extends WithDisposable(LitElement) { private readonly _onBlackBackgroundChange = (checked: boolean) => { this.blackBackground = checked; - this.edgeless.slots.navigatorSettingUpdated.emit({ + this.edgeless.slots.navigatorSettingUpdated.next({ blackBackground: this.blackBackground, }); }; @@ -134,7 +134,7 @@ export class EdgelessNavigatorSettingButton extends WithDisposable(LitElement) {
Black background
@@ -144,7 +144,7 @@ export class EdgelessNavigatorSettingButton extends WithDisposable(LitElement) {
Hide toolbar
{ this.onHideToolbarChange && this.onHideToolbarChange(checked); }} diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/presentation-toolbar.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/presentation-toolbar.ts index 407dfd10dd..edb61aca2e 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/presentation-toolbar.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/presentation-toolbar.ts @@ -197,7 +197,7 @@ export class PresentationToolbar extends EdgelessToolbarToolMixin( } viewport.setViewportByBound(bound, [0, 0, 0, 0], false); - this.edgeless.slots.navigatorFrameChanged.emit( + this.edgeless.slots.navigatorFrameChanged.next( this._frames[this._currentFrameIndex] ); } @@ -278,7 +278,7 @@ export class PresentationToolbar extends EdgelessToolbarToolMixin( this._bindHotKey(); _disposables.add( - edgeless.slots.navigatorSettingUpdated.on(({ fillScreen }) => { + edgeless.slots.navigatorSettingUpdated.subscribe(({ fillScreen }) => { if (fillScreen !== undefined) { this._navigatorMode = fillScreen ? 'fill' : 'fit'; } @@ -307,7 +307,7 @@ export class PresentationToolbar extends EdgelessToolbarToolMixin( } setTimeout(() => this._moveToCurrentFrame(), 400); - this.edgeless.slots.fullScreenToggled.emit(); + this.edgeless.slots.fullScreenToggled.next(); }); this._navigatorMode = diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/template/overlay-scrollbar.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/template/overlay-scrollbar.ts index 7b17de0154..baff1249f2 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/template/overlay-scrollbar.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/template/overlay-scrollbar.ts @@ -3,7 +3,7 @@ import { once, requestConnectedFrame, } from '@blocksuite/affine-shared/utils'; -import { DisposableGroup } from '@blocksuite/global/slot'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { css, html, LitElement } from 'lit'; import { query } from 'lit/decorators.js'; diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-keyboard.ts b/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-keyboard.ts index d5f3e40681..91301ab1d0 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-keyboard.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-keyboard.ts @@ -138,7 +138,7 @@ export class EdgelessPageKeyboardManager extends PageKeyboardManager { NoteBlockModel, ]) ) { - rootComponent.slots.toggleNoteSlicer.emit(); + rootComponent.slots.toggleNoteSlicer.next(); } }, f: () => { @@ -173,7 +173,7 @@ export class EdgelessPageKeyboardManager extends PageKeyboardManager { elements.length === 1 && isNoteBlock(elements[0]) ) { - rootComponent.slots.toggleNoteSlicer.emit(); + rootComponent.slots.toggleNoteSlicer.next(); } }, '@': () => { diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-root-block.ts b/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-root-block.ts index 019ae1aa34..74f4a2d13d 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-root-block.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-root-block.ts @@ -182,7 +182,7 @@ export class EdgelessRootBlockComponent extends BlockComponent< }); this._disposables.add( - this.gfx.layer.slots.layerUpdated.on(() => updateLayers()) + this.gfx.layer.slots.layerUpdated.subscribe(() => updateLayers()) ); } @@ -426,7 +426,7 @@ export class EdgelessRootBlockComponent extends BlockComponent< const dy = simulateHorizontalScroll ? 0 : e.deltaY / viewport.zoom; viewport.applyDeltaCenter(dx, dy); - viewport.viewportMoved.emit([dx, dy]); + viewport.viewportMoved.next([dx, dy]); e.stopPropagation(); } }) @@ -520,14 +520,14 @@ export class EdgelessRootBlockComponent extends BlockComponent< this.gfx.tool.setTool('default'); } - this.gfx.viewport.elementReady.emit(this.gfxViewportElm); + this.gfx.viewport.elementReady.next(this.gfxViewportElm); requestConnectedFrame(() => { this.requestUpdate(); }, this); this._disposables.add( - this.gfx.viewport.viewportUpdated.on(() => { + this.gfx.viewport.viewportUpdated.subscribe(() => { this._refreshLayerViewport(); }) ); diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-root-preview-block.ts b/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-root-preview-block.ts index eb74d94fb8..a11b6303ba 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-root-preview-block.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-root-preview-block.ts @@ -126,7 +126,7 @@ export class EdgelessRootPreviewBlockComponent extends BlockComponent< }); this._disposables.add( - this._gfx.layer.slots.layerUpdated.on(() => updateLayers()) + this._gfx.layer.slots.layerUpdated.subscribe(() => updateLayers()) ); } @@ -219,7 +219,7 @@ export class EdgelessRootPreviewBlockComponent extends BlockComponent< this._initLayerUpdateEffect(); this._disposables.add( - this._gfx.viewport.viewportUpdated.on(() => { + this._gfx.viewport.viewportUpdated.subscribe(() => { this._refreshLayerViewport(); }) ); diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-root-service.ts b/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-root-service.ts index 70fb66a557..d7c62225a4 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-root-service.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-root-service.ts @@ -152,7 +152,7 @@ export class EdgelessRootService extends RootService implements SurfaceContext { effect(() => { if (readonly !== doc.readonly) { readonly = doc.readonly; - slots.readonlyUpdated.emit(readonly); + slots.readonlyUpdated.next(readonly); } }) ); diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/default-tool.ts b/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/default-tool.ts index 3b3fca89e5..4c78c67ca7 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/default-tool.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/default-tool.ts @@ -42,9 +42,9 @@ import { isGfxGroupCompatibleModel, type PointTestOptions, } from '@blocksuite/block-std/gfx'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import type { IVec } from '@blocksuite/global/gfx'; import { Bound, getCommonBoundWithRotation, Vec } from '@blocksuite/global/gfx'; -import { DisposableGroup } from '@blocksuite/global/slot'; import { noop } from '@blocksuite/global/utils'; import { effect } from '@preact/signals-core'; import clamp from 'lodash-es/clamp'; @@ -598,7 +598,7 @@ export class DefaultTool extends BaseTool { // If the viewport updates when dragging, should update the dragging area and selection if (this.dragType === DefaultModeDragType.Selecting) { this._disposables.add( - this.gfx.viewport.viewportUpdated.on(() => { + this.gfx.viewport.viewportUpdated.subscribe(() => { if ( this.dragType === DefaultModeDragType.Selecting && this.controller.dragging$.peek() && @@ -613,7 +613,7 @@ export class DefaultTool extends BaseTool { if (this.dragType === DefaultModeDragType.ContentMoving) { this._disposables.add( - this.gfx.viewport.viewportMoved.on(delta => { + this.gfx.viewport.viewportMoved.subscribe(delta => { if ( this.dragType === DefaultModeDragType.ContentMoving && this.controller.dragging$.peek() && diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/note-tool.ts b/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/note-tool.ts index abf1311aa9..ced3d08b78 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/note-tool.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/note-tool.ts @@ -69,7 +69,7 @@ export class NoteTool extends BaseTool { endY = startY + (endY > startY ? m : -m); } - _draggingNoteOverlay.slots.draggingNoteUpdated.emit({ + _draggingNoteOverlay.slots.draggingNoteUpdated.next({ xywh: [ Math.min(startX, endX), Math.min(startY, endY), diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/services/template-middlewares.ts b/blocksuite/affine/blocks/block-root/src/edgeless/services/template-middlewares.ts index 8bd383e1a6..f065bbd0a0 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/services/template-middlewares.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/services/template-middlewares.ts @@ -9,7 +9,7 @@ import type { SlotBlockPayload, TemplateJob } from './template.js'; export const replaceIdMiddleware = (job: TemplateJob) => { const regeneratedIdMap = new Map(); - job.slots.beforeInsert.on(payload => { + job.slots.beforeInsert.subscribe(payload => { switch (payload.type) { case 'block': regenerateBlockId(payload.data); @@ -134,7 +134,7 @@ export const createInsertPlaceMiddleware = (targetPlace: Bound) => { y: number; }; - job.slots.beforeInsert.on(blockData => { + job.slots.beforeInsert.subscribe(blockData => { if (blockData.type === 'template') { templateBound = blockData.bound; @@ -211,7 +211,7 @@ export const createStickerMiddleware = ( getIndex: () => string ) => { return (job: TemplateJob) => { - job.slots.beforeInsert.on(blockData => { + job.slots.beforeInsert.subscribe(blockData => { if (blockData.type === 'block') { changeInserPosition(blockData.data.blockJson); } @@ -238,7 +238,7 @@ export const createRegenerateIndexMiddleware = ( generateIndex: () => string ) => { return (job: TemplateJob) => { - job.slots.beforeInsert.on(blockData => { + job.slots.beforeInsert.subscribe(blockData => { if (blockData.type === 'template') { generateIndexMap(); } diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/services/template.ts b/blocksuite/affine/blocks/block-root/src/edgeless/services/template.ts index f41e742c80..b1abd1ab68 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/services/template.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/services/template.ts @@ -4,7 +4,6 @@ import type { } from '@blocksuite/affine-block-surface'; import type { ConnectorElementModel } from '@blocksuite/affine-model'; import { Bound, getCommonBound } from '@blocksuite/global/gfx'; -import { Slot } from '@blocksuite/global/slot'; import { assertType } from '@blocksuite/global/utils'; import { type BlockModel, @@ -14,6 +13,7 @@ import { type SnapshotNode, type Transformer, } from '@blocksuite/store'; +import { Subject } from 'rxjs'; import type * as Y from 'yjs'; /** * Those block contains other block's id @@ -73,7 +73,7 @@ export class TemplateJob { model: SurfaceBlockModel; slots = { - beforeInsert: new Slot< + beforeInsert: new Subject< | SlotBlockPayload | { type: 'template'; @@ -255,7 +255,7 @@ export class TemplateJob { index, }; - this.slots.beforeInsert.emit({ type: 'block', data: slotData }); + this.slots.beforeInsert.next({ type: 'block', data: slotData }); /** * merge block should not be converted to model data @@ -340,7 +340,7 @@ export class TemplateJob { const templateBound = this._getTemplateBound(); - this.slots.beforeInsert.emit({ + this.slots.beforeInsert.next({ type: 'template', template: template, bound: templateBound, diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/utils/tool-overlay.ts b/blocksuite/affine/blocks/block-root/src/edgeless/utils/tool-overlay.ts index 10b07fb6b9..fdae24c26c 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/utils/tool-overlay.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/utils/tool-overlay.ts @@ -12,11 +12,12 @@ import { } from '@blocksuite/affine-model'; import { ThemeProvider } from '@blocksuite/affine-shared/services'; import type { GfxController, GfxToolsMap } from '@blocksuite/block-std/gfx'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import type { XYWH } from '@blocksuite/global/gfx'; import { Bound } from '@blocksuite/global/gfx'; -import { DisposableGroup, Slot } from '@blocksuite/global/slot'; import { assertType, noop } from '@blocksuite/global/utils'; import { effect } from '@preact/signals-core'; +import { Subject } from 'rxjs'; import type { ShapeTool } from '../gfx-tool/shape-tool.js'; import { @@ -237,7 +238,7 @@ class ToolOverlay extends Overlay { this.globalAlpha = 0; this.gfx = gfx; this.disposables.add( - this.gfx.viewport.viewportUpdated.on(() => { + this.gfx.viewport.viewportUpdated.subscribe(() => { // when viewport is updated, we should keep the overlay in the same position // to get last mouse position and convert it to model coordinates const pos = this.gfx.tool.lastMousePos$.value; @@ -444,7 +445,7 @@ export class DraggingNoteOverlay extends NoteOverlay { height: number; slots: { - draggingNoteUpdated: Slot<{ xywh: XYWH }>; + draggingNoteUpdated: Subject<{ xywh: XYWH }>; }; width: number; @@ -452,14 +453,14 @@ export class DraggingNoteOverlay extends NoteOverlay { constructor(gfx: GfxController, background: Color) { super(gfx, background); this.slots = { - draggingNoteUpdated: new Slot<{ + draggingNoteUpdated: new Subject<{ xywh: XYWH; }>(), }; this.width = 0; this.height = 0; this.disposables.add( - this.slots.draggingNoteUpdated.on(({ xywh }) => { + this.slots.draggingNoteUpdated.subscribe(({ xywh }) => { [this.x, this.y, this.width, this.height] = xywh; (this.gfx.surfaceComponent as SurfaceBlockComponent).refresh(); }) diff --git a/blocksuite/affine/blocks/block-root/src/page/page-root-block.ts b/blocksuite/affine/blocks/block-root/src/page/page-root-block.ts index 7456f378d9..5d39a03f19 100644 --- a/blocksuite/affine/blocks/block-root/src/page/page-root-block.ts +++ b/blocksuite/affine/blocks/block-root/src/page/page-root-block.ts @@ -214,7 +214,7 @@ export class PageRootBlockComponent extends BlockComponent< (entries: ResizeObserverEntry[]) => { for (const { target } of entries) { if (target === viewportElement) { - viewportService.emit(viewport); + viewportService.next(viewport); break; } } @@ -416,7 +416,7 @@ export class PageRootBlockComponent extends BlockComponent< ); noteModels.forEach(note => { this.disposables.add( - note.propsUpdated.on(({ key }) => { + note.propsUpdated.subscribe(({ key }) => { if (key === 'displayMode') { this.requestUpdate(); } diff --git a/blocksuite/affine/blocks/block-root/src/widgets/edgeless-navigator-bg/index.ts b/blocksuite/affine/blocks/block-root/src/widgets/edgeless-navigator-bg/index.ts index f0f1c43403..6c6ff4bdc5 100644 --- a/blocksuite/affine/blocks/block-root/src/widgets/edgeless-navigator-bg/index.ts +++ b/blocksuite/affine/blocks/block-root/src/widgets/edgeless-navigator-bg/index.ts @@ -42,13 +42,13 @@ export class EdgelessNavigatorBlackBackgroundWidget extends WidgetComponent { + this._slots.navigatorFrameChanged.subscribe(frame => { this.frame = frame; }) ); _disposables.add( - this._slots.navigatorSettingUpdated.on(({ blackBackground }) => { + this._slots.navigatorSettingUpdated.subscribe(({ blackBackground }) => { if (blackBackground !== undefined) { this.std .get(EditPropsStore) @@ -76,7 +76,7 @@ export class EdgelessNavigatorBlackBackgroundWidget extends WidgetComponent setTimeout(() => { this.requestUpdate(); diff --git a/blocksuite/affine/blocks/block-root/src/widgets/edgeless-zoom-toolbar/index.ts b/blocksuite/affine/blocks/block-root/src/widgets/edgeless-zoom-toolbar/index.ts index e7727db58b..8140623e17 100644 --- a/blocksuite/affine/blocks/block-root/src/widgets/edgeless-zoom-toolbar/index.ts +++ b/blocksuite/affine/blocks/block-root/src/widgets/edgeless-zoom-toolbar/index.ts @@ -63,7 +63,7 @@ export class AffineEdgelessZoomToolbarWidget extends WidgetComponent< const slots = std.get(EdgelessLegacySlotIdentifier); disposables.add( - slots.navigatorSettingUpdated.on(({ hideToolbar }) => { + slots.navigatorSettingUpdated.subscribe(({ hideToolbar }) => { if (hideToolbar !== undefined) { this._hide = hideToolbar; } diff --git a/blocksuite/affine/blocks/block-root/src/widgets/edgeless-zoom-toolbar/zoom-bar-toggle-button.ts b/blocksuite/affine/blocks/block-root/src/widgets/edgeless-zoom-toolbar/zoom-bar-toggle-button.ts index ff6588dc2d..2e5cbb956b 100644 --- a/blocksuite/affine/blocks/block-root/src/widgets/edgeless-zoom-toolbar/zoom-bar-toggle-button.ts +++ b/blocksuite/affine/blocks/block-root/src/widgets/edgeless-zoom-toolbar/zoom-bar-toggle-button.ts @@ -69,7 +69,7 @@ export class ZoomBarToggleButton extends WithDisposable(LitElement) { override firstUpdated() { const { disposables } = this; disposables.add( - this.edgeless.slots.readonlyUpdated.on(() => { + this.edgeless.slots.readonlyUpdated.subscribe(() => { this.requestUpdate(); }) ); diff --git a/blocksuite/affine/blocks/block-root/src/widgets/edgeless-zoom-toolbar/zoom-toolbar.ts b/blocksuite/affine/blocks/block-root/src/widgets/edgeless-zoom-toolbar/zoom-toolbar.ts index 503e757c9b..a507a735d0 100644 --- a/blocksuite/affine/blocks/block-root/src/widgets/edgeless-zoom-toolbar/zoom-toolbar.ts +++ b/blocksuite/affine/blocks/block-root/src/widgets/edgeless-zoom-toolbar/zoom-toolbar.ts @@ -130,12 +130,12 @@ export class EdgelessZoomToolbar extends WithDisposable(LitElement) { override firstUpdated() { const { disposables } = this; disposables.add( - this.edgeless.service.viewport.viewportUpdated.on(() => + this.edgeless.service.viewport.viewportUpdated.subscribe(() => this.requestUpdate() ) ); disposables.add( - this.edgeless.slots.readonlyUpdated.on(() => { + this.edgeless.slots.readonlyUpdated.subscribe(() => { this.requestUpdate(); }) ); diff --git a/blocksuite/affine/blocks/block-root/src/widgets/element-toolbar/align-button.ts b/blocksuite/affine/blocks/block-root/src/widgets/element-toolbar/align-button.ts index 31681ba98e..2b241f8374 100644 --- a/blocksuite/affine/blocks/block-root/src/widgets/element-toolbar/align-button.ts +++ b/blocksuite/affine/blocks/block-root/src/widgets/element-toolbar/align-button.ts @@ -304,7 +304,7 @@ export class EdgelessAlignButton extends WithDisposable(LitElement) { override firstUpdated() { this._disposables.add( - this.edgeless.service.selection.slots.updated.on(() => + this.edgeless.service.selection.slots.updated.subscribe(() => this.requestUpdate() ) ); diff --git a/blocksuite/affine/blocks/block-root/src/widgets/element-toolbar/change-note-button.ts b/blocksuite/affine/blocks/block-root/src/widgets/element-toolbar/change-note-button.ts index 1f908bdf0e..95a9449b3d 100644 --- a/blocksuite/affine/blocks/block-root/src/widgets/element-toolbar/change-note-button.ts +++ b/blocksuite/affine/blocks/block-root/src/widgets/element-toolbar/change-note-button.ts @@ -159,7 +159,7 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) { const surfaceService = this.edgeless.service; if (!surfaceService) return; - this.edgeless.slots.toggleNoteSlicer.emit(); + this.edgeless.slots.toggleNoteSlicer.next(); } private _setCollapse() { @@ -201,7 +201,7 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) { const clear = () => { this.doc.history.off('stack-item-added', addHandler); this.doc.history.off('stack-item-popped', popHandler); - disposable.dispose(); + disposable.unsubscribe(); }; const closeNotify = () => { abortController.abort(); @@ -212,7 +212,7 @@ export class EdgelessChangeNoteButton extends WithDisposable(LitElement) { const popHandler = this.doc.history.on('stack-item-popped', closeNotify); const disposable = this.edgeless.std .get(EditorLifeCycleExtension) - .slots.unmounted.on(closeNotify); + .slots.unmounted.subscribe(closeNotify); const undo = () => { this.doc.undo(); diff --git a/blocksuite/affine/blocks/block-root/src/widgets/element-toolbar/change-shape-button.ts b/blocksuite/affine/blocks/block-root/src/widgets/element-toolbar/change-shape-button.ts index 5a192ecd81..92b0cdab8f 100644 --- a/blocksuite/affine/blocks/block-root/src/widgets/element-toolbar/change-shape-button.ts +++ b/blocksuite/affine/blocks/block-root/src/widgets/element-toolbar/change-shape-button.ts @@ -232,7 +232,7 @@ export class EdgelessChangeShapeButton extends WithDisposable(LitElement) { const _disposables = this._disposables; _disposables.add( - this._shapePanel.slots.select.on(shapeName => { + this._shapePanel.slots.select.subscribe(shapeName => { this.edgeless.doc.captureSync(); this.elements.forEach(element => { this.crud.updateElement(element.id, { diff --git a/blocksuite/affine/blocks/block-root/src/widgets/element-toolbar/index.ts b/blocksuite/affine/blocks/block-root/src/widgets/element-toolbar/index.ts index 5f730ce707..d932fd2cb1 100644 --- a/blocksuite/affine/blocks/block-root/src/widgets/element-toolbar/index.ts +++ b/blocksuite/affine/blocks/block-root/src/widgets/element-toolbar/index.ts @@ -361,13 +361,13 @@ export class EdgelessElementToolbarWidget extends WidgetComponent< this.moreGroups = getMoreMenuConfig(this.std).configure(this.moreGroups); _disposables.add( - edgeless.service.viewport.viewportUpdated.on(() => { + edgeless.service.viewport.viewportUpdated.subscribe(() => { this._recalculatePosition(); }) ); _disposables.add( - this.selection.slots.updated.on(() => { + this.selection.slots.updated.subscribe(() => { if ( this.selection.selectedIds.length === 0 || this.selection.editing || @@ -383,18 +383,18 @@ export class EdgelessElementToolbarWidget extends WidgetComponent< ); _disposables.add( - this.edgeless.service.surface.elementAdded.on( + this.edgeless.service.surface.elementAdded.subscribe( this._updateOnSelectedChange ) ); _disposables.add( - this.edgeless.service.surface.elementUpdated.on( + this.edgeless.service.surface.elementUpdated.subscribe( this._updateOnSelectedChange ) ); _disposables.add( - this.doc.slots.blockUpdated.on(this._updateOnSelectedChange) + this.doc.slots.blockUpdated.subscribe(this._updateOnSelectedChange) ); _disposables.add( @@ -410,19 +410,19 @@ export class EdgelessElementToolbarWidget extends WidgetComponent< ); _disposables.add( - edgeless.slots.elementResizeStart.on(() => { + edgeless.slots.elementResizeStart.subscribe(() => { this._dragging = true; }) ); _disposables.add( - edgeless.slots.elementResizeEnd.on(() => { + edgeless.slots.elementResizeEnd.subscribe(() => { this._dragging = false; this._recalculatePosition(); }) ); _disposables.add( - edgeless.slots.readonlyUpdated.on(() => this.requestUpdate()) + edgeless.slots.readonlyUpdated.subscribe(() => this.requestUpdate()) ); this.updateComplete diff --git a/blocksuite/affine/blocks/block-root/src/widgets/keyboard-toolbar/config.ts b/blocksuite/affine/blocks/block-root/src/widgets/keyboard-toolbar/config.ts index 69666b65e7..6e9baea59a 100644 --- a/blocksuite/affine/blocks/block-root/src/widgets/keyboard-toolbar/config.ts +++ b/blocksuite/affine/blocks/block-root/src/widgets/keyboard-toolbar/config.ts @@ -359,13 +359,18 @@ const pageToolGroup: KeyboardToolPanelGroup = { const inlineEditor = getInlineEditorByModel(std.host, currentModel); // Wait for range to be updated - inlineEditor?.slots.inlineRangeSync.once(() => { - linkedDocWidget.show({ - mode: 'mobile', - addTriggerKey: true, - }); - closeToolPanel(); - }); + if (inlineEditor) { + const subscription = inlineEditor.slots.inlineRangeSync.subscribe( + () => { + subscription.unsubscribe(); + linkedDocWidget.show({ + mode: 'mobile', + addTriggerKey: true, + }); + closeToolPanel(); + } + ); + } }) .run(); }, diff --git a/blocksuite/affine/blocks/block-root/src/widgets/keyboard-toolbar/position-controller.ts b/blocksuite/affine/blocks/block-root/src/widgets/keyboard-toolbar/position-controller.ts index 3b8323f489..0822664e0c 100644 --- a/blocksuite/affine/blocks/block-root/src/widgets/keyboard-toolbar/position-controller.ts +++ b/blocksuite/affine/blocks/block-root/src/widgets/keyboard-toolbar/position-controller.ts @@ -1,6 +1,6 @@ import { type VirtualKeyboardProvider } from '@blocksuite/affine-shared/services'; import type { BlockStdScope, ShadowlessElement } from '@blocksuite/block-std'; -import { DisposableGroup } from '@blocksuite/global/slot'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { effect, type Signal } from '@preact/signals-core'; import type { ReactiveController, ReactiveControllerHost } from 'lit'; diff --git a/blocksuite/affine/blocks/block-root/src/widgets/linked-doc/index.ts b/blocksuite/affine/blocks/block-root/src/widgets/linked-doc/index.ts index 0196ad2162..01fb85931f 100644 --- a/blocksuite/affine/blocks/block-root/src/widgets/linked-doc/index.ts +++ b/blocksuite/affine/blocks/block-root/src/widgets/linked-doc/index.ts @@ -199,7 +199,7 @@ export class AffineLinkedDocWidget extends WidgetComponent< private _watchViewportChange() { const gfx = this.std.get(GfxControllerIdentifier); this.disposables.add( - gfx.viewport.viewportUpdated.on(() => { + gfx.viewport.viewportUpdated.subscribe(() => { this._updateInputRects(); }) ); @@ -273,7 +273,7 @@ export class AffineLinkedDocWidget extends WidgetComponent< }); } - const disposable = inlineEditor.slots.renderComplete.on(() => { + const disposable = inlineEditor.slots.renderComplete.subscribe(() => { this._updateInputRects(); }); this._context = { @@ -283,7 +283,7 @@ export class AffineLinkedDocWidget extends WidgetComponent< triggerKey: primaryTriggerKey, config: this.config, close: () => { - disposable.dispose(); + disposable.unsubscribe(); this._inputRects$.value = []; this._mode$.value = 'none'; this._context = null; diff --git a/blocksuite/affine/blocks/block-root/src/widgets/linked-doc/linked-doc-popover.ts b/blocksuite/affine/blocks/block-root/src/widgets/linked-doc/linked-doc-popover.ts index 1a76caa6af..d8a6945316 100644 --- a/blocksuite/affine/blocks/block-root/src/widgets/linked-doc/linked-doc-popover.ts +++ b/blocksuite/affine/blocks/block-root/src/widgets/linked-doc/linked-doc-popover.ts @@ -183,9 +183,11 @@ export class LinkedDocPopover extends SignalWatcher( if (isComposition) { this._updateLinkedDocGroup().catch(console.error); } else { - this.context.inlineEditor.slots.renderComplete.once( - this._updateLinkedDocGroup - ); + const subscription = + this.context.inlineEditor.slots.renderComplete.subscribe(() => { + subscription.unsubscribe(); + this._updateLinkedDocGroup().catch(console.error); + }); } }, onPaste: () => { @@ -201,9 +203,11 @@ export class LinkedDocPopover extends SignalWatcher( if (curRange.index < this.context.startRange.index) { this.context.close(); } - this.context.inlineEditor.slots.renderComplete.once( - this._updateLinkedDocGroup - ); + const subscription = + this.context.inlineEditor.slots.renderComplete.subscribe(() => { + subscription.unsubscribe(); + this._updateLinkedDocGroup().catch(console.error); + }); }, onMove: step => { const itemLen = this._flattenActionList.length; @@ -332,7 +336,9 @@ export class LinkedDocPopover extends SignalWatcher( } const gfx = this.context.std.get(GfxControllerIdentifier); - this.disposables.add(gfx.viewport.viewportUpdated.on(updatePosition)); + this.disposables.add( + gfx.viewport.viewportUpdated.subscribe(updatePosition) + ); updatePosition(); } diff --git a/blocksuite/affine/blocks/block-root/src/widgets/linked-doc/mobile-linked-doc-menu.ts b/blocksuite/affine/blocks/block-root/src/widgets/linked-doc/mobile-linked-doc-menu.ts index 308c01cfbe..afe4c61253 100644 --- a/blocksuite/affine/blocks/block-root/src/widgets/linked-doc/mobile-linked-doc-menu.ts +++ b/blocksuite/affine/blocks/block-root/src/widgets/linked-doc/mobile-linked-doc-menu.ts @@ -196,20 +196,28 @@ export class AffineMobileLinkedDocMenu extends SignalWatcher( if (isComposition) { this._updateLinkedDocGroup().catch(console.error); } else { - inlineEditor.slots.renderComplete.once(this._updateLinkedDocGroup); + const subscription = inlineEditor.slots.renderComplete.subscribe( + () => { + subscription.unsubscribe(); + this._updateLinkedDocGroup().catch(console.error); + } + ); } }, onDelete: () => { - inlineEditor.slots.renderComplete.once(() => { - const curRange = inlineEditor.getInlineRange(); + const subscription = inlineEditor.slots.renderComplete.subscribe( + () => { + subscription.unsubscribe(); + const curRange = inlineEditor.getInlineRange(); - if (!this.context.startRange || !curRange) return; + if (!this.context.startRange || !curRange) return; - if (curRange.index < this.context.startRange.index) { - this.context.close(); + if (curRange.index < this.context.startRange.index) { + this.context.close(); + } + this._updateLinkedDocGroup().catch(console.error); } - this._updateLinkedDocGroup().catch(console.error); - }); + ); }, onConfirm: () => { this._firstActionItem?.action()?.catch(console.error); diff --git a/blocksuite/affine/blocks/block-surface-ref/package.json b/blocksuite/affine/blocks/block-surface-ref/package.json index 0c708afb39..226610d0fe 100644 --- a/blocksuite/affine/blocks/block-surface-ref/package.json +++ b/blocksuite/affine/blocks/block-surface-ref/package.json @@ -31,6 +31,7 @@ "lit": "^3.2.0", "lodash-es": "^4.17.21", "nanoid": "^5.0.7", + "rxjs": "^7.8.1", "zod": "^3.23.8" }, "exports": { diff --git a/blocksuite/affine/blocks/block-surface-ref/src/portal/generic-block.ts b/blocksuite/affine/blocks/block-surface-ref/src/portal/generic-block.ts index e678551a66..76cd3c1034 100644 --- a/blocksuite/affine/blocks/block-surface-ref/src/portal/generic-block.ts +++ b/blocksuite/affine/blocks/block-surface-ref/src/portal/generic-block.ts @@ -30,7 +30,7 @@ export class SurfaceRefGenericBlockPortal extends WithDisposable( override firstUpdated() { this.disposables.add( - this.model.propsUpdated.on(() => this.requestUpdate()) + this.model.propsUpdated.subscribe(() => this.requestUpdate()) ); } diff --git a/blocksuite/affine/blocks/block-surface-ref/src/portal/note.ts b/blocksuite/affine/blocks/block-surface-ref/src/portal/note.ts index 4a691ed8d5..921820d20f 100644 --- a/blocksuite/affine/blocks/block-surface-ref/src/portal/note.ts +++ b/blocksuite/affine/blocks/block-surface-ref/src/portal/note.ts @@ -62,7 +62,7 @@ export class SurfaceRefNotePortal extends WithDisposable(ShadowlessElement) { override firstUpdated() { this.disposables.add( - this.model.propsUpdated.on(() => this.requestUpdate()) + this.model.propsUpdated.subscribe(() => this.requestUpdate()) ); } diff --git a/blocksuite/affine/blocks/block-surface-ref/src/surface-ref-block.ts b/blocksuite/affine/blocks/block-surface-ref/src/surface-ref-block.ts index ee43c08e6f..304b664a85 100644 --- a/blocksuite/affine/blocks/block-surface-ref/src/surface-ref-block.ts +++ b/blocksuite/affine/blocks/block-surface-ref/src/surface-ref-block.ts @@ -36,13 +36,13 @@ import { type GfxModel, GfxPrimitiveElementModel, } from '@blocksuite/block-std/gfx'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; import { Bound, deserializeXYWH, type SerializedXYWH, } from '@blocksuite/global/gfx'; -import { DisposableGroup } from '@blocksuite/global/slot'; import { DeleteIcon, EdgelessIcon, FrameIcon } from '@blocksuite/icons/lit'; import type { BaseSelection, Store } from '@blocksuite/store'; import { css, html, nothing, type TemplateResult } from 'lit'; @@ -376,7 +376,7 @@ export class SurfaceRefBlockComponent extends BlockComponent { + this.model.propsUpdated.subscribe(payload => { if ( payload.key === 'reference' && this.model.reference !== this._referencedModel?.id @@ -388,7 +388,7 @@ export class SurfaceRefBlockComponent extends BlockComponent { + surfaceModel.elementRemoved.subscribe(({ id }) => { if (this.model.reference === id) { init(); } @@ -398,7 +398,7 @@ export class SurfaceRefBlockComponent extends BlockComponent { + this.doc.slots.blockUpdated.subscribe(({ type, id }) => { if (type === 'delete' && id === this.model.reference) { init(); } @@ -410,7 +410,7 @@ export class SurfaceRefBlockComponent extends BlockComponent { + selection.slots.changed.subscribe(selList => { this._focused = selList.some( sel => sel.blockId === this.blockId && sel.is(BlockSelection) ); @@ -424,16 +424,16 @@ export class SurfaceRefBlockComponent extends BlockComponent { + const disposable = this.std.view.viewUpdated.subscribe(payload => { if (payload.type !== 'block') return; if ( payload.method === 'add' && matchModels(payload.view.model, [RootBlockModel]) ) { - disposable.dispose(); + disposable.unsubscribe(); queueMicrotask(() => refreshViewport()); const gfx = this.std.get(GfxControllerIdentifier); - gfx.viewport.sizeUpdated.on(() => { + gfx.viewport.sizeUpdated.subscribe(() => { refreshViewport(); }); } @@ -475,7 +475,7 @@ export class SurfaceRefBlockComponent extends BlockComponent { + surfaceModel.elementUpdated.subscribe(({ id, oldValues }) => { if ( id === referenceId && oldValues.xywh !== referenceElement.xywh diff --git a/blocksuite/affine/blocks/block-surface/package.json b/blocksuite/affine/blocks/block-surface/package.json index b8506cc199..0d77595de2 100644 --- a/blocksuite/affine/blocks/block-surface/package.json +++ b/blocksuite/affine/blocks/block-surface/package.json @@ -31,6 +31,7 @@ "lodash-es": "^4.17.21", "nanoid": "^5.0.7", "pdf-lib": "^1.17.1", + "rxjs": "^7.8.1", "yjs": "^13.6.21", "zod": "^3.23.8" }, diff --git a/blocksuite/affine/blocks/block-surface/src/extensions/legacy-slot-extension.ts b/blocksuite/affine/blocks/block-surface/src/extensions/legacy-slot-extension.ts index 7691d529cd..3fc5c57ccd 100644 --- a/blocksuite/affine/blocks/block-surface/src/extensions/legacy-slot-extension.ts +++ b/blocksuite/affine/blocks/block-surface/src/extensions/legacy-slot-extension.ts @@ -1,40 +1,39 @@ import type { FrameBlockModel } from '@blocksuite/affine-model'; import { createIdentifier } from '@blocksuite/global/di'; -import { Slot } from '@blocksuite/global/slot'; import type { ExtensionType } from '@blocksuite/store'; - +import { Subject } from 'rxjs'; export const EdgelessLegacySlotIdentifier = createIdentifier<{ - readonlyUpdated: Slot; - navigatorSettingUpdated: Slot<{ + readonlyUpdated: Subject; + navigatorSettingUpdated: Subject<{ hideToolbar?: boolean; blackBackground?: boolean; fillScreen?: boolean; }>; - navigatorFrameChanged: Slot; - fullScreenToggled: Slot; + navigatorFrameChanged: Subject; + fullScreenToggled: Subject; - elementResizeStart: Slot; - elementResizeEnd: Slot; - toggleNoteSlicer: Slot; + elementResizeStart: Subject; + elementResizeEnd: Subject; + toggleNoteSlicer: Subject; - toolbarLocked: Slot; + toolbarLocked: Subject; }>('AffineEdgelessLegacySlotService'); export const EdgelessLegacySlotExtension: ExtensionType = { setup: di => { di.addImpl(EdgelessLegacySlotIdentifier, () => ({ - readonlyUpdated: new Slot(), - navigatorSettingUpdated: new Slot<{ + readonlyUpdated: new Subject(), + navigatorSettingUpdated: new Subject<{ hideToolbar?: boolean; blackBackground?: boolean; fillScreen?: boolean; }>(), - navigatorFrameChanged: new Slot(), - fullScreenToggled: new Slot(), - elementResizeStart: new Slot(), - elementResizeEnd: new Slot(), - toggleNoteSlicer: new Slot(), - toolbarLocked: new Slot(), + navigatorFrameChanged: new Subject(), + fullScreenToggled: new Subject(), + elementResizeStart: new Subject(), + elementResizeEnd: new Subject(), + toggleNoteSlicer: new Subject(), + toolbarLocked: new Subject(), })); }, }; diff --git a/blocksuite/affine/blocks/block-surface/src/renderer/canvas-renderer.ts b/blocksuite/affine/blocks/block-surface/src/renderer/canvas-renderer.ts index 9d9b2e2f7e..a573374aaf 100644 --- a/blocksuite/affine/blocks/block-surface/src/renderer/canvas-renderer.ts +++ b/blocksuite/affine/blocks/block-surface/src/renderer/canvas-renderer.ts @@ -6,10 +6,11 @@ import type { SurfaceBlockModel, Viewport, } from '@blocksuite/block-std/gfx'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import type { IBound } from '@blocksuite/global/gfx'; import { getBoundWithRotation, intersects } from '@blocksuite/global/gfx'; -import { DisposableGroup, Slot } from '@blocksuite/global/slot'; import last from 'lodash-es/last'; +import { Subject } from 'rxjs'; import type { SurfaceElementModel } from '../element-model/base.js'; import { RoughCanvas } from '../utils/rough/canvas.js'; @@ -58,7 +59,7 @@ export class CanvasRenderer { provider: Partial; - stackingCanvasUpdated = new Slot<{ + stackingCanvasUpdated = new Subject<{ canvases: HTMLCanvasElement[]; added: HTMLCanvasElement[]; removed: HTMLCanvasElement[]; @@ -175,14 +176,14 @@ export class CanvasRenderer { payload.removed = currentCanvases.slice(diff); } - this.stackingCanvasUpdated.emit(payload); + this.stackingCanvasUpdated.next(payload); } this.refresh(); }; this._disposables.add( - this.layerManager.slots.layerUpdated.on(() => { + this.layerManager.slots.layerUpdated.subscribe(() => { updateStackingCanvas(); }) ); @@ -194,13 +195,13 @@ export class CanvasRenderer { let sizeUpdatedRafId: number | null = null; this._disposables.add( - this.viewport.viewportUpdated.on(() => { + this.viewport.viewportUpdated.subscribe(() => { this.refresh(); }) ); this._disposables.add( - this.viewport.sizeUpdated.on(() => { + this.viewport.sizeUpdated.subscribe(() => { if (sizeUpdatedRafId) return; sizeUpdatedRafId = requestConnectedFrame(() => { sizeUpdatedRafId = null; @@ -319,20 +320,24 @@ export class CanvasRenderer { } private _watchSurface(surfaceModel: SurfaceBlockModel) { - const slots = [ - 'elementAdded', - 'elementRemoved', - 'localElementAdded', - 'localElementDeleted', - 'localElementUpdated', - ] as const; - - slots.forEach(slotName => { - this._disposables.add(surfaceModel[slotName].on(() => this.refresh())); - }); + this._disposables.add( + surfaceModel.elementAdded.subscribe(() => this.refresh()) + ); + this._disposables.add( + surfaceModel.elementRemoved.subscribe(() => this.refresh()) + ); + this._disposables.add( + surfaceModel.localElementAdded.subscribe(() => this.refresh()) + ); + this._disposables.add( + surfaceModel.localElementDeleted.subscribe(() => this.refresh()) + ); + this._disposables.add( + surfaceModel.localElementUpdated.subscribe(() => this.refresh()) + ); this._disposables.add( - surfaceModel.elementUpdated.on(payload => { + surfaceModel.elementUpdated.subscribe(payload => { // ignore externalXYWH update cause it's updated by the renderer if (payload.props['externalXYWH']) return; this.refresh(); diff --git a/blocksuite/affine/blocks/block-surface/src/surface-block.ts b/blocksuite/affine/blocks/block-surface/src/surface-block.ts index 4b1f55d50e..a6655a8b94 100644 --- a/blocksuite/affine/blocks/block-surface/src/surface-block.ts +++ b/blocksuite/affine/blocks/block-surface/src/surface-block.ts @@ -7,9 +7,9 @@ import { type Viewport, } from '@blocksuite/block-std/gfx'; import { Bound } from '@blocksuite/global/gfx'; -import type { Slot } from '@blocksuite/global/slot'; import { css, html } from 'lit'; import { query } from 'lit/decorators.js'; +import type { Subject } from 'rxjs'; import { ConnectorElementModel } from './element-model/index.js'; import { CanvasRenderer } from './renderer/canvas-renderer.js'; @@ -28,7 +28,7 @@ export interface SurfaceContext { selection: { selectedIds: string[]; slots: { - updated: Slot; + updated: Subject; }; }; } @@ -191,7 +191,7 @@ export class SurfaceBlockComponent extends BlockComponent< this._renderer.dispose(); }); this._disposables.add( - this._renderer.stackingCanvasUpdated.on(payload => { + this._renderer.stackingCanvasUpdated.subscribe(payload => { if (payload.added.length) { this._surfaceContainer.append(...payload.added); } @@ -204,7 +204,7 @@ export class SurfaceBlockComponent extends BlockComponent< }) ); this._disposables.add( - gfx.selection.slots.updated.on(() => { + gfx.selection.slots.updated.subscribe(() => { this._renderer.refresh(); }) ); diff --git a/blocksuite/affine/blocks/block-surface/src/surface-model.ts b/blocksuite/affine/blocks/block-surface/src/surface-model.ts index fbe6c5cda5..3db3869206 100644 --- a/blocksuite/affine/blocks/block-surface/src/surface-model.ts +++ b/blocksuite/affine/blocks/block-surface/src/surface-model.ts @@ -4,7 +4,7 @@ import type { } from '@blocksuite/affine-model'; import type { SurfaceBlockProps } from '@blocksuite/block-std/gfx'; import { SurfaceBlockModel as BaseSurfaceModel } from '@blocksuite/block-std/gfx'; -import { DisposableGroup } from '@blocksuite/global/slot'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { BlockSchemaExtension, defineBlockSchema } from '@blocksuite/store'; import * as Y from 'yjs'; diff --git a/blocksuite/affine/blocks/block-surface/src/surface-service.ts b/blocksuite/affine/blocks/block-surface/src/surface-service.ts index eea96f973e..dd15975e2a 100644 --- a/blocksuite/affine/blocks/block-surface/src/surface-service.ts +++ b/blocksuite/affine/blocks/block-surface/src/surface-service.ts @@ -22,9 +22,9 @@ export class SurfaceBlockService extends BlockService { this.surface = surface!; if (!this.surface) { - const disposable = this.doc.slots.blockUpdated.on(payload => { + const disposable = this.doc.slots.blockUpdated.subscribe(payload => { if (payload.flavour === 'affine:surface') { - disposable.dispose(); + disposable.unsubscribe(); const surface = this.doc.getBlockById( payload.id ) as SurfaceBlockModel | null; diff --git a/blocksuite/affine/blocks/block-surface/src/view/mindmap.ts b/blocksuite/affine/blocks/block-surface/src/view/mindmap.ts index 3e0036830f..ba0f68e0de 100644 --- a/blocksuite/affine/blocks/block-surface/src/view/mindmap.ts +++ b/blocksuite/affine/blocks/block-surface/src/view/mindmap.ts @@ -61,7 +61,7 @@ export class MindMapView extends GfxElementModelView { }); this.disposable.add( - this.model.propsUpdated.on(({ key }) => { + this.model.propsUpdated.subscribe(({ key }) => { if (key === 'layoutType' || key === 'style') { updateButtons(); } @@ -69,7 +69,7 @@ export class MindMapView extends GfxElementModelView { ); this.disposable.add( - this.surface.elementUpdated.on(payload => { + this.surface.elementUpdated.subscribe(payload => { if (this.model.children.has(payload.id)) { if (payload.props['xywh']) { updateButtons(); @@ -142,7 +142,7 @@ export class MindMapView extends GfxElementModelView { private _setVisibleOnSelection() { let lastNode: null | string = null; this.disposable.add( - this.gfx.selection.slots.updated.on(() => { + this.gfx.selection.slots.updated.subscribe(() => { const elm = this.gfx.selection.firstElement; if (lastNode) { diff --git a/blocksuite/affine/blocks/block-surface/src/watchers/connector.ts b/blocksuite/affine/blocks/block-surface/src/watchers/connector.ts index e4672503f0..2046fc3069 100644 --- a/blocksuite/affine/blocks/block-surface/src/watchers/connector.ts +++ b/blocksuite/affine/blocks/block-surface/src/watchers/connector.ts @@ -37,7 +37,7 @@ export const connectorWatcher: SurfaceMiddleware = ( }; const disposables = [ - surface.elementAdded.on(({ id }) => { + surface.elementAdded.subscribe(({ id }) => { const element = elementGetter(id); if (!element) return; @@ -48,7 +48,7 @@ export const connectorWatcher: SurfaceMiddleware = ( surface.getConnectors(id).forEach(addToUpdateList); } }), - surface.elementUpdated.on(({ id, props }) => { + surface.elementUpdated.subscribe(({ id, props }) => { const element = elementGetter(id); if (props['xywh'] || props['rotate']) { @@ -66,7 +66,7 @@ export const connectorWatcher: SurfaceMiddleware = ( addToUpdateList(element as ConnectorElementModel); } }), - surface.doc.slots.blockUpdated.on(payload => { + surface.doc.slots.blockUpdated.subscribe(payload => { if ( payload.type === 'add' || (payload.type === 'update' && payload.props.key === 'xywh') @@ -83,6 +83,6 @@ export const connectorWatcher: SurfaceMiddleware = ( ); return () => { - disposables.forEach(d => d.dispose()); + disposables.forEach(d => d.unsubscribe()); }; }; diff --git a/blocksuite/affine/blocks/block-surface/src/watchers/group.ts b/blocksuite/affine/blocks/block-surface/src/watchers/group.ts index 3b58696fc8..58671c7c0c 100644 --- a/blocksuite/affine/blocks/block-surface/src/watchers/group.ts +++ b/blocksuite/affine/blocks/block-surface/src/watchers/group.ts @@ -5,23 +5,23 @@ export const groupRelationWatcher: SurfaceMiddleware = ( surface: SurfaceBlockModel ) => { const disposables = [ - surface.elementUpdated - .filter(payload => payload.local) - .on(({ id, props }) => { - const element = surface.getElementById(id)!; + surface.elementUpdated.subscribe(({ id, props, local }) => { + if (!local) return; - // remove the group if it has no children - if ( - element instanceof SurfaceGroupLikeModel && - props['childIds'] && - element.childIds.length === 0 - ) { - surface.deleteElement(id); - } - }), + const element = surface.getElementById(id)!; + + // remove the group if it has no children + if ( + element instanceof SurfaceGroupLikeModel && + props['childIds'] && + element.childIds.length === 0 + ) { + surface.deleteElement(id); + } + }), ]; return () => { - disposables.forEach(d => d.dispose()); + disposables.forEach(d => d.unsubscribe()); }; }; diff --git a/blocksuite/affine/blocks/block-table/package.json b/blocksuite/affine/blocks/block-table/package.json index 11ec3dc5cc..0c5c620fdf 100644 --- a/blocksuite/affine/blocks/block-table/package.json +++ b/blocksuite/affine/blocks/block-table/package.json @@ -28,6 +28,7 @@ "@preact/signals-core": "^1.8.0", "@vanilla-extract/css": "^1.17.0", "lit": "^3.2.0", + "rxjs": "^7.8.1", "yjs": "^13.6.21", "zod": "^3.24.1" }, diff --git a/blocksuite/affine/components/package.json b/blocksuite/affine/components/package.json index 7122438703..3c86c74820 100644 --- a/blocksuite/affine/components/package.json +++ b/blocksuite/affine/components/package.json @@ -36,6 +36,7 @@ "lit-html": "^3.2.1", "lodash-es": "^4.17.21", "remark-math": "^6.0.0", + "rxjs": "^7.8.1", "shiki": "^3.0.0", "yjs": "^13.6.21", "zod": "^3.23.8" diff --git a/blocksuite/affine/components/src/caption/block-caption.ts b/blocksuite/affine/components/src/caption/block-caption.ts index 63257ed111..702618b786 100644 --- a/blocksuite/affine/components/src/caption/block-caption.ts +++ b/blocksuite/affine/components/src/caption/block-caption.ts @@ -124,7 +124,7 @@ export class BlockCaptionEditor< this.caption = this.model.caption; this.disposables.add( - this.model.propsUpdated.on(({ key }) => { + this.model.propsUpdated.subscribe(({ key }) => { if (key === 'caption') { this.caption = this.model.caption; if (!this._focus) { diff --git a/blocksuite/affine/components/src/embed-card-modal/embed-card-edit-modal.ts b/blocksuite/affine/components/src/embed-card-modal/embed-card-edit-modal.ts index fee0b942a5..6572ce77f2 100644 --- a/blocksuite/affine/components/src/embed-card-modal/embed-card-edit-modal.ts +++ b/blocksuite/affine/components/src/embed-card-modal/embed-card-edit-modal.ts @@ -258,7 +258,9 @@ export class EmbedCardEditModal extends SignalWatcher( super.connectedCallback(); this.disposables.add( - this.host.std.get(EditorLifeCycleExtension).slots.unmounted.on(this._hide) + this.host.std + .get(EditorLifeCycleExtension) + .slots.unmounted.subscribe(this._hide) ); this._updateInfo(); } diff --git a/blocksuite/affine/components/src/filterable-list/index.ts b/blocksuite/affine/components/src/filterable-list/index.ts index 3353645476..d7e8195f70 100644 --- a/blocksuite/affine/components/src/filterable-list/index.ts +++ b/blocksuite/affine/components/src/filterable-list/index.ts @@ -204,7 +204,7 @@ export function showPopFilterableList({ createLitPortal({ closeOnClickAway: true, template: ({ positionSlot }) => { - positionSlot.on(({ placement }) => { + positionSlot.subscribe(({ placement }) => { list.placement = placement; }); diff --git a/blocksuite/affine/components/src/hover/controller.ts b/blocksuite/affine/components/src/hover/controller.ts index a066c19f00..4cf959d1f8 100644 --- a/blocksuite/affine/components/src/hover/controller.ts +++ b/blocksuite/affine/components/src/hover/controller.ts @@ -1,4 +1,4 @@ -import { DisposableGroup } from '@blocksuite/global/slot'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import type { ReactiveController, ReactiveElement } from 'lit'; import { diff --git a/blocksuite/affine/components/src/notification/linked-doc.ts b/blocksuite/affine/components/src/notification/linked-doc.ts index 18f57a9fbe..80162de31c 100644 --- a/blocksuite/affine/components/src/notification/linked-doc.ts +++ b/blocksuite/affine/components/src/notification/linked-doc.ts @@ -19,7 +19,7 @@ function notify(std: BlockStdScope, title: string, message: string) { const clear = () => { doc.history.off('stack-item-added', addHandler); doc.history.off('stack-item-popped', popHandler); - disposable.dispose(); + disposable.unsubscribe(); }; const closeNotify = () => { abortController.abort(); @@ -31,7 +31,7 @@ function notify(std: BlockStdScope, title: string, message: string) { const popHandler = doc.history.on('stack-item-popped', closeNotify); const disposable = host.std .get(EditorLifeCycleExtension) - .slots.unmounted.on(closeNotify); + .slots.unmounted.subscribe(closeNotify); notification.notify({ title, diff --git a/blocksuite/affine/components/src/portal/helper.ts b/blocksuite/affine/components/src/portal/helper.ts index 2260307e32..2244fd4653 100644 --- a/blocksuite/affine/components/src/portal/helper.ts +++ b/blocksuite/affine/components/src/portal/helper.ts @@ -1,5 +1,4 @@ import { BlockSuiteError } from '@blocksuite/global/exceptions'; -import { Slot } from '@blocksuite/global/slot'; import { autoUpdate, computePosition, @@ -7,6 +6,7 @@ import { } from '@floating-ui/dom'; import { cssVar } from '@toeverything/theme'; import { render } from 'lit'; +import { Subject } from 'rxjs'; import type { AdvancedPortalOptions, PortalOptions } from './types.js'; @@ -127,13 +127,13 @@ export function createLitPortal({ positionStrategy = 'absolute', ...portalOptions }: AdvancedPortalOptions) { - let positionSlot = new Slot(); + let positionSlot = new Subject(); const template = portalOptions.template; const templateWithPosition = template instanceof Function ? ({ updatePortal }: { updatePortal: () => void }) => { // We need to create a new slot for each template, otherwise the slot may be used in the old template - positionSlot = new Slot(); + positionSlot = new Subject(); return template({ updatePortal, positionSlot }); } : template; @@ -199,7 +199,7 @@ export function createLitPortal({ if (portalRoot.style.visibility === 'hidden') { portalRoot.style.visibility = visibility; } - positionSlot.emit(positionReturn); + positionSlot.next(positionReturn); }) .catch(console.error); }; diff --git a/blocksuite/affine/components/src/portal/types.ts b/blocksuite/affine/components/src/portal/types.ts index 2c98c41459..de1dd6c9df 100644 --- a/blocksuite/affine/components/src/portal/types.ts +++ b/blocksuite/affine/components/src/portal/types.ts @@ -1,4 +1,3 @@ -import type { Slot } from '@blocksuite/global/slot'; import type { AutoUpdateOptions, ComputePositionConfig, @@ -6,6 +5,7 @@ import type { ReferenceElement, } from '@floating-ui/dom'; import type { RenderOptions, TemplateResult } from 'lit'; +import type { Subject } from 'rxjs'; /** * See https://lit.dev/docs/templates/expressions/#child-expressions @@ -64,7 +64,7 @@ export type AdvancedPortalOptions = Omit< template: | Renderable | ((context: { - positionSlot: Slot; + positionSlot: Subject; updatePortal: () => void; }) => Renderable); positionStrategy?: 'absolute' | 'fixed'; diff --git a/blocksuite/affine/components/src/toggle-switch/index.ts b/blocksuite/affine/components/src/toggle-switch/index.ts index 0e60bf5df1..2597cf5f32 100644 --- a/blocksuite/affine/components/src/toggle-switch/index.ts +++ b/blocksuite/affine/components/src/toggle-switch/index.ts @@ -38,11 +38,11 @@ const styles = css` transition: 0.1s; } - label.on { + label.subscribe { background: var(--affine-primary-color); } - label.on:after { + label.subscribe:after { left: calc(100% - 1px); transform: translateX(-100%); } diff --git a/blocksuite/affine/components/src/toolbar/tooltip.ts b/blocksuite/affine/components/src/toolbar/tooltip.ts index d1bec091b2..1d080f0fbc 100644 --- a/blocksuite/affine/components/src/toolbar/tooltip.ts +++ b/blocksuite/affine/components/src/toolbar/tooltip.ts @@ -144,7 +144,7 @@ export class Tooltip extends LitElement { let arrowStyles: StyleInfo = {}; return { template: ({ positionSlot, updatePortal }) => { - positionSlot.on(data => { + positionSlot.subscribe(data => { // The tooltip placement may change, // so we need to update the arrow position if (this.arrow) { diff --git a/blocksuite/affine/data-view/package.json b/blocksuite/affine/data-view/package.json index 40db67fae8..aa072f7a95 100644 --- a/blocksuite/affine/data-view/package.json +++ b/blocksuite/affine/data-view/package.json @@ -29,6 +29,7 @@ "date-fns": "^4.0.0", "lit": "^3.2.0", "lodash-es": "^4.17.21", + "rxjs": "^7.8.1", "yjs": "^13.6.21", "zod": "^3.23.8" }, diff --git a/blocksuite/affine/data-view/src/core/property/types.ts b/blocksuite/affine/data-view/src/core/property/types.ts index 567f5ed42b..8fc6080af9 100644 --- a/blocksuite/affine/data-view/src/core/property/types.ts +++ b/blocksuite/affine/data-view/src/core/property/types.ts @@ -1,4 +1,4 @@ -import type { Disposable } from '@blocksuite/global/slot'; +import type { Disposable } from '@blocksuite/global/disposable'; import type { ZodType } from 'zod'; import type { DataSource } from '../data-source/base.js'; diff --git a/blocksuite/affine/data-view/src/core/view/types.ts b/blocksuite/affine/data-view/src/core/view/types.ts index f27f5a917f..3f1b738f85 100644 --- a/blocksuite/affine/data-view/src/core/view/types.ts +++ b/blocksuite/affine/data-view/src/core/view/types.ts @@ -8,7 +8,7 @@ import type { EventName, UIEventHandler, } from '@blocksuite/block-std'; -import type { Disposable } from '@blocksuite/global/slot'; +import type { Disposable } from '@blocksuite/global/disposable'; import type { ReadonlySignal } from '@preact/signals-core'; import type { DataSource } from '../common/index.js'; diff --git a/blocksuite/affine/fragments/fragment-doc-title/package.json b/blocksuite/affine/fragments/fragment-doc-title/package.json index 3e5065d1ea..3f5d4f13e8 100644 --- a/blocksuite/affine/fragments/fragment-doc-title/package.json +++ b/blocksuite/affine/fragments/fragment-doc-title/package.json @@ -30,6 +30,7 @@ "@toeverything/theme": "^1.1.12", "lit": "^3.2.0", "minimatch": "^10.0.1", + "rxjs": "^7.8.1", "zod": "^3.23.8" }, "exports": { diff --git a/blocksuite/affine/fragments/fragment-frame-panel/package.json b/blocksuite/affine/fragments/fragment-frame-panel/package.json index 3524abd2d5..53a0b3819f 100644 --- a/blocksuite/affine/fragments/fragment-frame-panel/package.json +++ b/blocksuite/affine/fragments/fragment-frame-panel/package.json @@ -32,6 +32,7 @@ "lit": "^3.2.0", "lodash-es": "^4.17.21", "minimatch": "^10.0.1", + "rxjs": "^7.8.1", "zod": "^3.23.8" }, "exports": { diff --git a/blocksuite/affine/fragments/fragment-frame-panel/src/body/frame-panel-body.ts b/blocksuite/affine/fragments/fragment-frame-panel/src/body/frame-panel-body.ts index 0a0bdb9a6b..1f3da856a1 100644 --- a/blocksuite/affine/fragments/fragment-frame-panel/src/body/frame-panel-body.ts +++ b/blocksuite/affine/fragments/fragment-frame-panel/src/body/frame-panel-body.ts @@ -9,9 +9,9 @@ import { generateKeyBetweenV2, GfxControllerIdentifier, } from '@blocksuite/block-std/gfx'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { Bound } from '@blocksuite/global/gfx'; import { SignalWatcher, WithDisposable } from '@blocksuite/global/lit'; -import { DisposableGroup } from '@blocksuite/global/slot'; import type { Store } from '@blocksuite/store'; import { css, html, nothing, type PropertyValues } from 'lit'; import { property, query, state } from 'lit/decorators.js'; @@ -326,7 +326,7 @@ export class FramePanelBody extends SignalWatcher( this._clearDocDisposables(); this._docDisposables = new DisposableGroup(); this._docDisposables.add( - doc.slots.blockUpdated.on(({ type, flavour }) => { + doc.slots.blockUpdated.subscribe(({ type, flavour }) => { if (flavour === 'affine:frame' && type !== 'update') { requestAnimationFrame(() => { this._updateFrames(); diff --git a/blocksuite/affine/fragments/fragment-frame-panel/src/card/frame-card-title-editor.ts b/blocksuite/affine/fragments/fragment-frame-panel/src/card/frame-card-title-editor.ts index 614e94298a..a0e6b0c036 100644 --- a/blocksuite/affine/fragments/fragment-frame-panel/src/card/frame-card-title-editor.ts +++ b/blocksuite/affine/fragments/fragment-frame-panel/src/card/frame-card-title-editor.ts @@ -39,7 +39,7 @@ export class FrameCardTitleEditor extends WithDisposable(ShadowlessElement) { this.inlineEditor.selectAll(); - this.inlineEditor.slots.renderComplete.on(() => { + this.inlineEditor.slots.renderComplete.subscribe(() => { this.requestUpdate(); }); diff --git a/blocksuite/affine/fragments/fragment-frame-panel/src/card/frame-card-title.ts b/blocksuite/affine/fragments/fragment-frame-panel/src/card/frame-card-title.ts index 507d345b65..584403e44e 100644 --- a/blocksuite/affine/fragments/fragment-frame-panel/src/card/frame-card-title.ts +++ b/blocksuite/affine/fragments/fragment-frame-panel/src/card/frame-card-title.ts @@ -1,7 +1,7 @@ import type { FrameBlockModel } from '@blocksuite/affine-model'; import { ShadowlessElement } from '@blocksuite/block-std'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { WithDisposable } from '@blocksuite/global/lit'; -import { DisposableGroup } from '@blocksuite/global/slot'; import { css, html, type PropertyValues } from 'lit'; import { property, query } from 'lit/decorators.js'; import type * as Y from 'yjs'; diff --git a/blocksuite/affine/fragments/fragment-frame-panel/src/card/frame-preview.ts b/blocksuite/affine/fragments/fragment-frame-panel/src/card/frame-preview.ts index 3c73668dc7..74ac18d7ab 100644 --- a/blocksuite/affine/fragments/fragment-frame-panel/src/card/frame-preview.ts +++ b/blocksuite/affine/fragments/fragment-frame-panel/src/card/frame-preview.ts @@ -8,9 +8,9 @@ import { ShadowlessElement, } from '@blocksuite/block-std'; import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { Bound, deserializeXYWH } from '@blocksuite/global/gfx'; import { WithDisposable } from '@blocksuite/global/lit'; -import { DisposableGroup } from '@blocksuite/global/slot'; import { type Query, type Store } from '@blocksuite/store'; import { css, html, nothing, type PropertyValues } from 'lit'; import { property, query, state } from 'lit/decorators.js'; @@ -122,7 +122,7 @@ export class FramePreview extends WithDisposable(ShadowlessElement) { override mounted() { const std = this.std; const { view } = std; - view.viewUpdated.on(payload => { + view.viewUpdated.subscribe(payload => { if ( payload.type !== 'block' || payload.method !== 'add' || @@ -131,7 +131,8 @@ export class FramePreview extends WithDisposable(ShadowlessElement) { return; } const viewport = std.get(GfxControllerIdentifier).viewport; - viewport.sizeUpdated.once(() => { + const subscription = viewport.sizeUpdated.subscribe(() => { + subscription.unsubscribe(); refreshViewport(); }); }); @@ -186,7 +187,7 @@ export class FramePreview extends WithDisposable(ShadowlessElement) { this._clearFrameDisposables(); this._frameDisposables = new DisposableGroup(); this._frameDisposables.add( - frame.propsUpdated.on( + frame.propsUpdated.subscribe( debounce(this._updateFrameViewportWH, 10, { leading: true }) ) ); diff --git a/blocksuite/affine/fragments/fragment-frame-panel/src/header/frame-panel-header.ts b/blocksuite/affine/fragments/fragment-frame-panel/src/header/frame-panel-header.ts index 4345f5689f..aab25292a6 100644 --- a/blocksuite/affine/fragments/fragment-frame-panel/src/header/frame-panel-header.ts +++ b/blocksuite/affine/fragments/fragment-frame-panel/src/header/frame-panel-header.ts @@ -7,8 +7,8 @@ import { import { createButtonPopper } from '@blocksuite/affine-shared/utils'; import type { EditorHost } from '@blocksuite/block-std'; import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { WithDisposable } from '@blocksuite/global/lit'; -import { DisposableGroup } from '@blocksuite/global/slot'; import { PresentationIcon, SettingsIcon } from '@blocksuite/icons/lit'; import { css, html, LitElement, type PropertyValues } from 'lit'; import { property, query, state } from 'lit/decorators.js'; @@ -143,7 +143,7 @@ export class FramePanelHeader extends WithDisposable(LitElement) { this._clearEdgelessDisposables(); this._edgelessDisposables = new DisposableGroup(); this._edgelessDisposables.add( - slots.navigatorSettingUpdated.on(({ fillScreen }) => { + slots.navigatorSettingUpdated.subscribe(({ fillScreen }) => { this._navigatorMode = fillScreen ? 'fill' : 'fit'; }) ); diff --git a/blocksuite/affine/fragments/fragment-frame-panel/src/header/frames-setting-menu.ts b/blocksuite/affine/fragments/fragment-frame-panel/src/header/frames-setting-menu.ts index 009ecbceee..46b455e304 100644 --- a/blocksuite/affine/fragments/fragment-frame-panel/src/header/frames-setting-menu.ts +++ b/blocksuite/affine/fragments/fragment-frame-panel/src/header/frames-setting-menu.ts @@ -82,14 +82,14 @@ export class FramesSettingMenu extends WithDisposable(LitElement) { private readonly _onBlackBackgroundChange = (checked: boolean) => { this.blackBackground = checked; - this.slots.navigatorSettingUpdated.emit({ + this.slots.navigatorSettingUpdated.next({ blackBackground: this.blackBackground, }); }; private readonly _onFillScreenChange = (checked: boolean) => { this.fillScreen = checked; - this.slots.navigatorSettingUpdated.emit({ + this.slots.navigatorSettingUpdated.next({ fillScreen: this.fillScreen, }); this._editPropsStore.setStorage('presentFillScreen', this.fillScreen); @@ -97,7 +97,7 @@ export class FramesSettingMenu extends WithDisposable(LitElement) { private readonly _onHideToolBarChange = (checked: boolean) => { this.hideToolbar = checked; - this.slots.navigatorSettingUpdated.emit({ + this.slots.navigatorSettingUpdated.next({ hideToolbar: this.hideToolbar, }); this._editPropsStore.setStorage('presentHideToolbar', this.hideToolbar); @@ -138,7 +138,7 @@ export class FramesSettingMenu extends WithDisposable(LitElement) {
Fill Screen
@@ -153,7 +153,7 @@ export class FramesSettingMenu extends WithDisposable(LitElement) {
Dark background
@@ -162,7 +162,7 @@ export class FramesSettingMenu extends WithDisposable(LitElement) {
Hide toolbar
@@ -175,7 +175,7 @@ export class FramesSettingMenu extends WithDisposable(LitElement) { const docModeProvider = this.editorHost.std.get(DocModeProvider); if (docModeProvider.getEditorMode() === 'edgeless') { this.disposables.add( - this.slots.navigatorSettingUpdated.on( + this.slots.navigatorSettingUpdated.subscribe( ({ blackBackground, hideToolbar }) => { if ( blackBackground !== undefined && diff --git a/blocksuite/affine/fragments/fragment-outline/package.json b/blocksuite/affine/fragments/fragment-outline/package.json index 87e1c92c3d..9fec9a3b1b 100644 --- a/blocksuite/affine/fragments/fragment-outline/package.json +++ b/blocksuite/affine/fragments/fragment-outline/package.json @@ -31,6 +31,7 @@ "@vanilla-extract/css": "^1.17.0", "lit": "^3.2.0", "minimatch": "^10.0.1", + "rxjs": "^7.8.1", "zod": "^3.23.8" }, "exports": { diff --git a/blocksuite/affine/fragments/fragment-outline/src/header/outline-setting-menu.ts b/blocksuite/affine/fragments/fragment-outline/src/header/outline-setting-menu.ts index 0de9703d2d..7528943dc9 100644 --- a/blocksuite/affine/fragments/fragment-outline/src/header/outline-setting-menu.ts +++ b/blocksuite/affine/fragments/fragment-outline/src/header/outline-setting-menu.ts @@ -26,7 +26,7 @@ export class OutlineNotePreviewSettingMenu extends SignalWatcher(
Show type icon
{ this._context.showIcons$.value = !showPreviewIcon; }} diff --git a/blocksuite/affine/fragments/fragment-outline/src/outline-viewer.ts b/blocksuite/affine/fragments/fragment-outline/src/outline-viewer.ts index c48248d05e..d104cac379 100644 --- a/blocksuite/affine/fragments/fragment-outline/src/outline-viewer.ts +++ b/blocksuite/affine/fragments/fragment-outline/src/outline-viewer.ts @@ -201,7 +201,7 @@ export class OutlineViewer extends SignalWatcher( ); this.disposables.add( - this.editor.doc.workspace.meta.docMetaUpdated.on(() => { + this.editor.doc.workspace.meta.docMetaUpdated.subscribe(() => { this.requestUpdate(); }) ); diff --git a/blocksuite/affine/fragments/fragment-outline/src/utils/scroll.ts b/blocksuite/affine/fragments/fragment-outline/src/utils/scroll.ts index 7f9af85ce1..9c900e9f20 100644 --- a/blocksuite/affine/fragments/fragment-outline/src/utils/scroll.ts +++ b/blocksuite/affine/fragments/fragment-outline/src/utils/scroll.ts @@ -3,8 +3,8 @@ import { NoteDisplayMode } from '@blocksuite/affine-model'; import { DocModeProvider } from '@blocksuite/affine-shared/services'; import type { Viewport } from '@blocksuite/affine-shared/types'; import type { EditorHost } from '@blocksuite/block-std'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { clamp } from '@blocksuite/global/gfx'; -import { DisposableGroup } from '@blocksuite/global/slot'; import { getHeadingBlocksFromDoc } from './query.js'; diff --git a/blocksuite/affine/gfx/text/package.json b/blocksuite/affine/gfx/text/package.json index 8e07a2dc56..6d078b6204 100644 --- a/blocksuite/affine/gfx/text/package.json +++ b/blocksuite/affine/gfx/text/package.json @@ -31,6 +31,7 @@ "lit": "^3.2.0", "lodash-es": "^4.17.21", "minimatch": "^10.0.1", + "rxjs": "^7.8.1", "yjs": "^13.6.21", "zod": "^3.23.8" }, diff --git a/blocksuite/affine/gfx/text/src/edgeless-text-editor.ts b/blocksuite/affine/gfx/text/src/edgeless-text-editor.ts index aceaa75272..94bd6f4c63 100644 --- a/blocksuite/affine/gfx/text/src/edgeless-text-editor.ts +++ b/blocksuite/affine/gfx/text/src/edgeless-text-editor.ts @@ -178,19 +178,19 @@ export class EdgelessTextEditor extends WithDisposable(ShadowlessElement) { this.updateComplete .then(() => { if (!this.inlineEditor) return; - this.inlineEditor.slots.renderComplete.on(() => { + this.inlineEditor.slots.renderComplete.subscribe(() => { this._updateRect(); this.requestUpdate(); }); this.disposables.add( - surface.elementUpdated.on(({ id }) => { + surface.elementUpdated.subscribe(({ id }) => { if (id === element.id) this.requestUpdate(); }) ); this.disposables.add( - this.gfx.viewport.viewportUpdated.on(() => { + this.gfx.viewport.viewportUpdated.subscribe(() => { this.requestUpdate(); }) ); diff --git a/blocksuite/affine/gfx/turbo-renderer/package.json b/blocksuite/affine/gfx/turbo-renderer/package.json index 608693488b..d57b42705d 100644 --- a/blocksuite/affine/gfx/turbo-renderer/package.json +++ b/blocksuite/affine/gfx/turbo-renderer/package.json @@ -17,6 +17,7 @@ "@blocksuite/global": "workspace:*", "@types/lodash-es": "^4.17.12", "lodash-es": "^4.17.21", + "rxjs": "^7.8.1", "tweakpane": "^4.0.5" }, "exports": { diff --git a/blocksuite/affine/gfx/turbo-renderer/src/turbo-renderer.ts b/blocksuite/affine/gfx/turbo-renderer/src/turbo-renderer.ts index ef7c68a292..fdbe177d90 100644 --- a/blocksuite/affine/gfx/turbo-renderer/src/turbo-renderer.ts +++ b/blocksuite/affine/gfx/turbo-renderer/src/turbo-renderer.ts @@ -8,7 +8,7 @@ import { type GfxViewportElement, } from '@blocksuite/block-std/gfx'; import type { Container, ServiceIdentifier } from '@blocksuite/global/di'; -import { DisposableGroup } from '@blocksuite/global/slot'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import debounce from 'lodash-es/debounce'; import { @@ -46,16 +46,17 @@ export class ViewportTurboRendererExtension extends LifeCycleWatcher { initTweakpane(this, mountPoint as HTMLElement); } - this.viewport.elementReady.once(element => { + const subscription = this.viewport.elementReady.subscribe(element => { + subscription.unsubscribe(); this.viewportElement = element; syncCanvasSize(this.canvas, this.std.host); this.setState('pending'); this.disposables.add( - this.viewport.sizeUpdated.on(() => this.handleResize()) + this.viewport.sizeUpdated.subscribe(() => this.handleResize()) ); this.disposables.add( - this.viewport.viewportUpdated.on(() => { + this.viewport.viewportUpdated.subscribe(() => { this.refresh().catch(console.error); }) ); @@ -74,10 +75,10 @@ export class ViewportTurboRendererExtension extends LifeCycleWatcher { }); this.disposables.add( - this.selection.slots.updated.on(() => this.invalidate()) + this.selection.slots.updated.subscribe(() => this.invalidate()) ); this.disposables.add( - this.std.store.slots.blockUpdated.on(() => this.invalidate()) + this.std.store.slots.blockUpdated.subscribe(() => this.invalidate()) ); } diff --git a/blocksuite/affine/model/package.json b/blocksuite/affine/model/package.json index 3e4988a8b9..576a2dc75f 100644 --- a/blocksuite/affine/model/package.json +++ b/blocksuite/affine/model/package.json @@ -21,6 +21,7 @@ "@types/lodash-es": "^4.17.12", "fractional-indexing": "^3.2.0", "lodash-es": "^4.17.21", + "rxjs": "^7.8.1", "yjs": "^13.6.21", "zod": "^3.23.8" }, diff --git a/blocksuite/affine/model/src/blocks/root/root-block-model.ts b/blocksuite/affine/model/src/blocks/root/root-block-model.ts index 854aa82947..99b045b332 100644 --- a/blocksuite/affine/model/src/blocks/root/root-block-model.ts +++ b/blocksuite/affine/model/src/blocks/root/root-block-model.ts @@ -12,8 +12,9 @@ export type RootBlockProps = { export class RootBlockModel extends BlockModel { constructor() { super(); - this.created.once(() => { - this.doc.slots.rootAdded.on(id => { + const createdSubscription = this.created.subscribe(() => { + createdSubscription.unsubscribe(); + this.doc.slots.rootAdded.subscribe(id => { const model = this.doc.getBlockById(id); if (model instanceof RootBlockModel) { const newDocMeta = this.doc.workspace.meta.getDocMeta(model.doc.id); diff --git a/blocksuite/affine/rich-text/package.json b/blocksuite/affine/rich-text/package.json index c72c70e7f0..50e1780765 100644 --- a/blocksuite/affine/rich-text/package.json +++ b/blocksuite/affine/rich-text/package.json @@ -37,6 +37,7 @@ "lit-html": "^3.2.1", "lodash-es": "^4.17.21", "remark-math": "^6.0.0", + "rxjs": "^7.8.1", "shiki": "^3.0.0", "yjs": "^13.6.21", "zod": "^3.23.8" diff --git a/blocksuite/affine/rich-text/src/dom.ts b/blocksuite/affine/rich-text/src/dom.ts index 699c734095..ded4f29f1d 100644 --- a/blocksuite/affine/rich-text/src/dom.ts +++ b/blocksuite/affine/rich-text/src/dom.ts @@ -109,7 +109,8 @@ export async function onModelTextUpdated( console.error('Inline editor is not ready yet.'); return; } - inlineEditor.slots.renderComplete.once(() => { + const subscription = inlineEditor.slots.renderComplete.subscribe(() => { + subscription.unsubscribe(); if (callback) { callback(richText); } diff --git a/blocksuite/affine/rich-text/src/extension/ref-node-slots.ts b/blocksuite/affine/rich-text/src/extension/ref-node-slots.ts index 36b9ef22db..f4e77569e1 100644 --- a/blocksuite/affine/rich-text/src/extension/ref-node-slots.ts +++ b/blocksuite/affine/rich-text/src/extension/ref-node-slots.ts @@ -1,6 +1,6 @@ import { createIdentifier } from '@blocksuite/global/di'; -import { Slot } from '@blocksuite/global/slot'; import type { ExtensionType } from '@blocksuite/store'; +import { Subject } from 'rxjs'; import type { RefNodeSlots } from '../inline/index.js'; @@ -8,7 +8,7 @@ export const RefNodeSlotsProvider = createIdentifier('AffineRefNodeSlots'); const slots: RefNodeSlots = { - docLinkClicked: new Slot(), + docLinkClicked: new Subject(), }; export const RefNodeSlotsExtension: ExtensionType = { diff --git a/blocksuite/affine/rich-text/src/inline/presets/nodes/link-node/affine-link.ts b/blocksuite/affine/rich-text/src/inline/presets/nodes/link-node/affine-link.ts index 2229dec28f..b1dff8b460 100644 --- a/blocksuite/affine/rich-text/src/inline/presets/nodes/link-node/affine-link.ts +++ b/blocksuite/affine/rich-text/src/inline/presets/nodes/link-node/affine-link.ts @@ -57,7 +57,7 @@ export class AffineLink extends WithDisposable(ShadowlessElement) { e?.preventDefault(); - refNodeSlotsProvider.docLinkClicked.emit({ + refNodeSlotsProvider.docLinkClicked.next({ ...referenceInfo, host: this.std.host, }); diff --git a/blocksuite/affine/rich-text/src/inline/presets/nodes/reference-node/reference-node.ts b/blocksuite/affine/rich-text/src/inline/presets/nodes/reference-node/reference-node.ts index 3146ae4118..caa1e20975 100644 --- a/blocksuite/affine/rich-text/src/inline/presets/nodes/reference-node/reference-node.ts +++ b/blocksuite/affine/rich-text/src/inline/presets/nodes/reference-node/reference-node.ts @@ -148,7 +148,7 @@ export class AffineReference extends WithDisposable(ShadowlessElement) { readonly open = (event?: Partial) => { if (!this.config.interactable) return; - this.std.getOptional(RefNodeSlotsProvider)?.docLinkClicked.emit({ + this.std.getOptional(RefNodeSlotsProvider)?.docLinkClicked.next({ ...this.referenceInfo, ...event, host: this.std.host, @@ -205,7 +205,9 @@ export class AffineReference extends WithDisposable(ShadowlessElement) { const doc = this.doc; if (doc) { this._disposables.add( - doc.workspace.slots.docListUpdated.on(() => this._updateRefMeta(doc)) + doc.workspace.slots.docListUpdated.subscribe(() => + this._updateRefMeta(doc) + ) ); } @@ -215,7 +217,9 @@ export class AffineReference extends WithDisposable(ShadowlessElement) { // observe yText update this.disposables.add( - this.inlineEditor.slots.textChange.on(() => this._updateRefMeta(doc)) + this.inlineEditor.slots.textChange.subscribe(() => + this._updateRefMeta(doc) + ) ); }) .catch(console.error); diff --git a/blocksuite/affine/rich-text/src/inline/presets/nodes/reference-node/types.ts b/blocksuite/affine/rich-text/src/inline/presets/nodes/reference-node/types.ts index 6159e305bb..24aa43dfb2 100644 --- a/blocksuite/affine/rich-text/src/inline/presets/nodes/reference-node/types.ts +++ b/blocksuite/affine/rich-text/src/inline/presets/nodes/reference-node/types.ts @@ -1,7 +1,7 @@ import type { ReferenceInfo } from '@blocksuite/affine-model'; import type { OpenDocMode } from '@blocksuite/affine-shared/services'; import type { EditorHost } from '@blocksuite/block-std'; -import type { Slot } from '@blocksuite/global/slot'; +import type { Subject } from 'rxjs'; export type DocLinkClickedEvent = ReferenceInfo & { // default is active view @@ -11,5 +11,5 @@ export type DocLinkClickedEvent = ReferenceInfo & { }; export type RefNodeSlots = { - docLinkClicked: Slot; + docLinkClicked: Subject; }; diff --git a/blocksuite/affine/shared/package.json b/blocksuite/affine/shared/package.json index 81906b8b8c..97c4f7343a 100644 --- a/blocksuite/affine/shared/package.json +++ b/blocksuite/affine/shared/package.json @@ -47,6 +47,7 @@ "remark-math": "^6.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", + "rxjs": "^7.8.1", "unified": "^11.0.5", "yjs": "^13.6.21", "zod": "^3.23.8" diff --git a/blocksuite/affine/shared/src/adapters/middlewares/copy.ts b/blocksuite/affine/shared/src/adapters/middlewares/copy.ts index 6d2b9f43c9..ea7d73d955 100644 --- a/blocksuite/affine/shared/src/adapters/middlewares/copy.ts +++ b/blocksuite/affine/shared/src/adapters/middlewares/copy.ts @@ -37,7 +37,7 @@ const handlePoint = ( }; const sliceText = (slots: TransformerSlots, std: EditorHost['std']) => { - slots.afterExport.on(payload => { + slots.afterExport.subscribe(payload => { if (payload.type === 'block') { const snapshot = payload.snapshot; diff --git a/blocksuite/affine/shared/src/adapters/middlewares/file-name.ts b/blocksuite/affine/shared/src/adapters/middlewares/file-name.ts index 01fe47c4c1..cb6e71abf4 100644 --- a/blocksuite/affine/shared/src/adapters/middlewares/file-name.ts +++ b/blocksuite/affine/shared/src/adapters/middlewares/file-name.ts @@ -3,7 +3,7 @@ import type { TransformerMiddleware } from '@blocksuite/store'; export const fileNameMiddleware = (fileName?: string): TransformerMiddleware => ({ slots }) => { - slots.beforeImport.on(payload => { + slots.beforeImport.subscribe(payload => { if (payload.type !== 'page') { return; } diff --git a/blocksuite/affine/shared/src/adapters/middlewares/paste.ts b/blocksuite/affine/shared/src/adapters/middlewares/paste.ts index 2ca42e780e..6dc3795cfe 100644 --- a/blocksuite/affine/shared/src/adapters/middlewares/paste.ts +++ b/blocksuite/affine/shared/src/adapters/middlewares/paste.ts @@ -516,7 +516,7 @@ export const pasteMiddleware = ( ): TransformerMiddleware => { return ({ slots }) => { let tr: PasteTr | undefined; - slots.beforeImport.on(payload => { + slots.beforeImport.subscribe(payload => { if (payload.type === 'slice') { const { snapshot } = payload; flatNote(snapshot); @@ -531,7 +531,7 @@ export const pasteMiddleware = ( } } }); - slots.afterImport.on(payload => { + slots.afterImport.subscribe(payload => { if (tr && payload.type === 'slice') { tr.pasted(); tr.focusPasted(); diff --git a/blocksuite/affine/shared/src/adapters/middlewares/replace-id.ts b/blocksuite/affine/shared/src/adapters/middlewares/replace-id.ts index 3aaa0387ee..113c542062 100644 --- a/blocksuite/affine/shared/src/adapters/middlewares/replace-id.ts +++ b/blocksuite/affine/shared/src/adapters/middlewares/replace-id.ts @@ -13,7 +13,7 @@ export const replaceIdMiddleware = (idGenerator: () => string): TransformerMiddleware => ({ slots, docCRUD }) => { const idMap = new Map(); - slots.afterImport.on(payload => { + slots.afterImport.subscribe(payload => { if ( payload.type === 'block' && payload.snapshot.flavour === 'affine:database' @@ -112,7 +112,7 @@ export const replaceIdMiddleware = } } }); - slots.beforeImport.on(payload => { + slots.beforeImport.subscribe(payload => { if (payload.type === 'page') { if (idMap.has(payload.snapshot.meta.id)) { payload.snapshot.meta.id = idMap.get(payload.snapshot.meta.id)!; diff --git a/blocksuite/affine/shared/src/adapters/middlewares/surface-ref-to-embed.ts b/blocksuite/affine/shared/src/adapters/middlewares/surface-ref-to-embed.ts index 6c3951b476..835a112155 100644 --- a/blocksuite/affine/shared/src/adapters/middlewares/surface-ref-to-embed.ts +++ b/blocksuite/affine/shared/src/adapters/middlewares/surface-ref-to-embed.ts @@ -5,12 +5,12 @@ export const surfaceRefToEmbed = (std: BlockStdScope): TransformerMiddleware => ({ slots }) => { let pageId: string | null = null; - slots.beforeImport.on(payload => { + slots.beforeImport.subscribe(payload => { if (payload.type === 'slice') { pageId = payload.snapshot.pageId; } }); - slots.beforeImport.on(payload => { + slots.beforeImport.subscribe(payload => { if ( pageId && payload.type === 'block' && diff --git a/blocksuite/affine/shared/src/adapters/middlewares/title.ts b/blocksuite/affine/shared/src/adapters/middlewares/title.ts index 4ad24cc1ff..83cdfbe046 100644 --- a/blocksuite/affine/shared/src/adapters/middlewares/title.ts +++ b/blocksuite/affine/shared/src/adapters/middlewares/title.ts @@ -3,7 +3,7 @@ import type { DocMeta, TransformerMiddleware } from '@blocksuite/store'; export const titleMiddleware = (metas: DocMeta[]): TransformerMiddleware => ({ slots, adapterConfigs }) => { - slots.beforeExport.on(() => { + slots.beforeExport.subscribe(() => { for (const meta of metas) { adapterConfigs.set('title:' + meta.id, meta.title); } diff --git a/blocksuite/affine/shared/src/services/block-meta-service.ts b/blocksuite/affine/shared/src/services/block-meta-service.ts index 61f3e32db2..fbbc01f36a 100644 --- a/blocksuite/affine/shared/src/services/block-meta-service.ts +++ b/blocksuite/affine/shared/src/services/block-meta-service.ts @@ -21,7 +21,7 @@ export class BlockMetaService extends StoreExtension { override loaded() { this.store.disposableGroup.add( - this.store.slots.blockUpdated.on(({ type, id }) => { + this.store.slots.blockUpdated.subscribe(({ type, id }) => { if (!this.isBlockMetaEnabled) return; const model = this.store.getBlock(id)?.model; diff --git a/blocksuite/affine/shared/src/services/doc-display-meta-service.ts b/blocksuite/affine/shared/src/services/doc-display-meta-service.ts index dc04ea7a82..d480c89db8 100644 --- a/blocksuite/affine/shared/src/services/doc-display-meta-service.ts +++ b/blocksuite/affine/shared/src/services/doc-display-meta-service.ts @@ -1,7 +1,10 @@ import type { AliasInfo, ReferenceParams } from '@blocksuite/affine-model'; import { LifeCycleWatcher, StdIdentifier } from '@blocksuite/block-std'; import { type Container, createIdentifier } from '@blocksuite/global/di'; -import type { Disposable } from '@blocksuite/global/slot'; +import { + type DisposableMember, + disposeMember, +} from '@blocksuite/global/disposable'; import { AliasIcon, BlockLinkIcon, @@ -68,7 +71,7 @@ export class DocDisplayMetaService static override key = 'doc-display-meta'; - readonly disposables: Disposable[] = []; + readonly disposables: DisposableMember[] = []; readonly iconMap = new WeakMap>(); @@ -80,7 +83,10 @@ export class DocDisplayMetaService dispose() { while (this.disposables.length > 0) { - this.disposables.pop()?.dispose(); + const disposable = this.disposables.pop(); + if (disposable) { + disposeMember(disposable); + } } } @@ -113,18 +119,19 @@ export class DocDisplayMetaService }, pageId); this.disposables.push(disposable); - this.disposables.push( - this.std.workspace.slots.docRemoved - .filter(docId => docId === doc.id) - .once(() => { + const docRemovedSubscription = + this.std.workspace.slots.docRemoved.subscribe(docId => { + if (docId === doc.id) { + docRemovedSubscription.unsubscribe(); const index = this.disposables.findIndex(d => d === disposable); if (index !== -1) { this.disposables.splice(index, 1); - disposable.dispose(); + disposable.unsubscribe(); } this.iconMap.delete(doc); - }) - ); + } + }); + this.disposables.push(docRemovedSubscription); this.iconMap.set(doc, icon$); } @@ -162,23 +169,26 @@ export class DocDisplayMetaService if (!title$) { title$ = signal(doc.meta?.title || 'Untitled'); - const disposable = this.std.workspace.slots.docListUpdated.on(() => { - title$!.value = doc.meta?.title || 'Untitled'; - }); + const disposable = this.std.workspace.slots.docListUpdated.subscribe( + () => { + title$!.value = doc.meta?.title || 'Untitled'; + } + ); this.disposables.push(disposable); - this.disposables.push( - this.std.workspace.slots.docRemoved - .filter(docId => docId === doc.id) - .once(() => { + const docRemovedSubscription = + this.std.workspace.slots.docRemoved.subscribe(docId => { + if (docId === doc.id) { + docRemovedSubscription.unsubscribe(); const index = this.disposables.findIndex(d => d === disposable); if (index !== -1) { this.disposables.splice(index, 1); - disposable.dispose(); + disposable.unsubscribe(); } - this.titleMap.delete(doc); - }) - ); + this.iconMap.delete(doc); + } + }); + this.disposables.push(docRemovedSubscription); this.titleMap.set(doc, title$); } diff --git a/blocksuite/affine/shared/src/services/doc-mode-service.ts b/blocksuite/affine/shared/src/services/doc-mode-service.ts index 8df1ab32e0..4da8dac867 100644 --- a/blocksuite/affine/shared/src/services/doc-mode-service.ts +++ b/blocksuite/affine/shared/src/services/doc-mode-service.ts @@ -1,10 +1,10 @@ import type { DocMode } from '@blocksuite/affine-model'; import type { Container } from '@blocksuite/global/di'; import { createIdentifier } from '@blocksuite/global/di'; -import { type Disposable, Slot } from '@blocksuite/global/slot'; import { noop } from '@blocksuite/global/utils'; import type { ExtensionType } from '@blocksuite/store'; import { Extension } from '@blocksuite/store'; +import { Subject, type Subscription } from 'rxjs'; const DEFAULT_MODE: DocMode = 'page'; @@ -42,7 +42,7 @@ export interface DocModeProvider { onPrimaryModeChange: ( handler: (mode: DocMode) => void, docId: string - ) => Disposable; + ) => Subscription; /** * Set the editor mode. Normally, it would be used to set the mode of the current editor. * When patch or override the doc mode service, can pass a callback to set the editor mode. @@ -61,7 +61,7 @@ export const DocModeProvider = createIdentifier( ); const modeMap = new Map(); -const slotMap = new Map>(); +const slotMap = new Map>(); export class DocModeService extends Extension implements DocModeProvider { static override setup(di: Container) { @@ -78,9 +78,9 @@ export class DocModeService extends Extension implements DocModeProvider { onPrimaryModeChange(handler: (mode: DocMode) => void, id: string) { if (!slotMap.get(id)) { - slotMap.set(id, new Slot()); + slotMap.set(id, new Subject()); } - return slotMap.get(id)!.on(handler); + return slotMap.get(id)!.subscribe(handler); } setEditorMode(mode: DocMode) { @@ -89,7 +89,7 @@ export class DocModeService extends Extension implements DocModeProvider { setPrimaryMode(mode: DocMode, id: string) { modeMap.set(id, mode); - slotMap.get(id)?.emit(mode); + slotMap.get(id)?.next(mode); } togglePrimaryMode(id: string) { diff --git a/blocksuite/affine/shared/src/services/edit-props-store.ts b/blocksuite/affine/shared/src/services/edit-props-store.ts index 3504846ae5..699f8f4979 100644 --- a/blocksuite/affine/shared/src/services/edit-props-store.ts +++ b/blocksuite/affine/shared/src/services/edit-props-store.ts @@ -1,11 +1,12 @@ import { ColorSchema } from '@blocksuite/affine-model'; import { type BlockStdScope, LifeCycleWatcher } from '@blocksuite/block-std'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; -import { DisposableGroup, Slot } from '@blocksuite/global/slot'; import type { DeepPartial } from '@blocksuite/global/utils'; import { computed, type Signal, signal } from '@preact/signals-core'; import clonedeep from 'lodash-es/cloneDeep'; import mergeWith from 'lodash-es/mergeWith'; +import { Subject } from 'rxjs'; import * as Y from 'yjs'; import { z } from 'zod'; @@ -79,7 +80,7 @@ export class EditPropsStore extends LifeCycleWatcher { lastProps$: Signal; slots = { - storageUpdated: new Slot<{ + storageUpdated: new Subject<{ key: StoragePropsKey; value: StorageProps[StoragePropsKey]; }>(), @@ -198,7 +199,7 @@ export class EditPropsStore extends LifeCycleWatcher { JSON.stringify(value) ); if (oldValue === value) return; - this.slots.storageUpdated.emit({ key, value }); + this.slots.storageUpdated.next({ key, value }); } override unmounted() { diff --git a/blocksuite/affine/shared/src/services/page-viewport-service.ts b/blocksuite/affine/shared/src/services/page-viewport-service.ts index 1880271a7b..373e09b9da 100644 --- a/blocksuite/affine/shared/src/services/page-viewport-service.ts +++ b/blocksuite/affine/shared/src/services/page-viewport-service.ts @@ -1,15 +1,15 @@ import { createIdentifier } from '@blocksuite/global/di'; -import { Slot } from '@blocksuite/global/slot'; import type { ExtensionType } from '@blocksuite/store'; +import { Subject } from 'rxjs'; import type { Viewport } from '../types'; -export const PageViewportService = createIdentifier>( +export const PageViewportService = createIdentifier>( 'PageViewportService' ); export const PageViewportServiceExtension: ExtensionType = { setup: di => { - di.addImpl(PageViewportService, () => new Slot()); + di.addImpl(PageViewportService, () => new Subject()); }, }; diff --git a/blocksuite/affine/shared/src/utils/button-popper.ts b/blocksuite/affine/shared/src/utils/button-popper.ts index bc5c30f095..d6904517f2 100644 --- a/blocksuite/affine/shared/src/utils/button-popper.ts +++ b/blocksuite/affine/shared/src/utils/button-popper.ts @@ -1,4 +1,4 @@ -import type { Disposable } from '@blocksuite/global/slot'; +import type { Disposable } from '@blocksuite/global/disposable'; import { autoPlacement, autoUpdate, diff --git a/blocksuite/affine/widgets/widget-drag-handle/package.json b/blocksuite/affine/widgets/widget-drag-handle/package.json index c0e0a47c14..058ed3eb8c 100644 --- a/blocksuite/affine/widgets/widget-drag-handle/package.json +++ b/blocksuite/affine/widgets/widget-drag-handle/package.json @@ -34,6 +34,7 @@ "lit": "^3.2.0", "lodash-es": "^4.17.21", "minimatch": "^10.0.1", + "rxjs": "^7.8.1", "zod": "^3.23.8" }, "exports": { diff --git a/blocksuite/affine/widgets/widget-drag-handle/src/drag-handle.ts b/blocksuite/affine/widgets/widget-drag-handle/src/drag-handle.ts index c08779256f..26c1bf4f74 100644 --- a/blocksuite/affine/widgets/widget-drag-handle/src/drag-handle.ts +++ b/blocksuite/affine/widgets/widget-drag-handle/src/drag-handle.ts @@ -7,8 +7,8 @@ import { } from '@blocksuite/affine-shared/utils'; import { type BlockComponent, WidgetComponent } from '@blocksuite/block-std'; import type { GfxModel } from '@blocksuite/block-std/gfx'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import type { IVec, Point, Rect } from '@blocksuite/global/gfx'; -import { DisposableGroup } from '@blocksuite/global/slot'; import { computed, type ReadonlySignal, signal } from '@preact/signals-core'; import { html, nothing } from 'lit'; import { query, state } from 'lit/decorators.js'; @@ -100,10 +100,12 @@ export class AffineDragHandleWidget extends WidgetComponent { this._anchorModelDisposables = new DisposableGroup(); this._anchorModelDisposables.add( - blockModel.propsUpdated.on(() => this.hide()) + blockModel.propsUpdated.subscribe(() => this.hide()) ); - this._anchorModelDisposables.add(blockModel.deleted.on(() => this.hide())); + this._anchorModelDisposables.add( + blockModel.deleted.subscribe(() => this.hide()) + ); }; hide = (force = false) => { diff --git a/blocksuite/affine/widgets/widget-drag-handle/src/helpers/preview-helper.ts b/blocksuite/affine/widgets/widget-drag-handle/src/helpers/preview-helper.ts index 50ef054f36..50ebc87efb 100644 --- a/blocksuite/affine/widgets/widget-drag-handle/src/helpers/preview-helper.ts +++ b/blocksuite/affine/widgets/widget-drag-handle/src/helpers/preview-helper.ts @@ -144,7 +144,7 @@ export class PreviewHelper { return; } - this.std.view.viewUpdated.on(payload => { + this.std.view.viewUpdated.subscribe(payload => { if (payload.type !== 'block') return; if (payload.view.model.flavour === 'affine:page') { diff --git a/blocksuite/affine/widgets/widget-drag-handle/src/middleware/blocks-filter.ts b/blocksuite/affine/widgets/widget-drag-handle/src/middleware/blocks-filter.ts index 794c3489ef..30128d0866 100644 --- a/blocksuite/affine/widgets/widget-drag-handle/src/middleware/blocks-filter.ts +++ b/blocksuite/affine/widgets/widget-drag-handle/src/middleware/blocks-filter.ts @@ -40,7 +40,7 @@ export const gfxBlocksFilter = ( } return ({ slots, transformerConfigs }) => { - slots.beforeExport.on(payload => { + slots.beforeExport.subscribe(payload => { if (payload.type !== 'block') { return; } @@ -54,7 +54,7 @@ export const gfxBlocksFilter = ( } }); - slots.afterExport.on(payload => { + slots.afterExport.subscribe(payload => { if (payload.type !== 'block') { return; } diff --git a/blocksuite/affine/widgets/widget-drag-handle/src/middleware/new-id-cross-doc.ts b/blocksuite/affine/widgets/widget-drag-handle/src/middleware/new-id-cross-doc.ts index 02ae4bb61a..c11ca250dc 100644 --- a/blocksuite/affine/widgets/widget-drag-handle/src/middleware/new-id-cross-doc.ts +++ b/blocksuite/affine/widgets/widget-drag-handle/src/middleware/new-id-cross-doc.ts @@ -9,7 +9,7 @@ export const newIdCrossDoc = let samePage = false; const oldToNewIdMap = new Map(); - slots.beforeImport.on(payload => { + slots.beforeImport.subscribe(payload => { if (payload.type === 'slice') { samePage = payload.snapshot.pageId === std.store.id; } @@ -21,7 +21,7 @@ export const newIdCrossDoc = } }); - slots.afterImport.on(payload => { + slots.afterImport.subscribe(payload => { if ( !samePage && payload.type === 'block' && diff --git a/blocksuite/affine/widgets/widget-drag-handle/src/middleware/reorder-list.ts b/blocksuite/affine/widgets/widget-drag-handle/src/middleware/reorder-list.ts index 4c69538b01..3e9f55c5e5 100644 --- a/blocksuite/affine/widgets/widget-drag-handle/src/middleware/reorder-list.ts +++ b/blocksuite/affine/widgets/widget-drag-handle/src/middleware/reorder-list.ts @@ -7,7 +7,7 @@ import type { TransformerMiddleware } from '@blocksuite/store'; export const reorderList = (std: BlockStdScope): TransformerMiddleware => ({ slots }) => { - slots.afterImport.on(payload => { + slots.afterImport.subscribe(payload => { if (payload.type === 'block') { const model = payload.model; if (matchModels(model, [ListBlockModel]) && model.type === 'numbered') { diff --git a/blocksuite/affine/widgets/widget-drag-handle/src/watchers/drag-event-watcher.ts b/blocksuite/affine/widgets/widget-drag-handle/src/watchers/drag-event-watcher.ts index 9accdfd9ab..24cd7638c1 100644 --- a/blocksuite/affine/widgets/widget-drag-handle/src/watchers/drag-event-watcher.ts +++ b/blocksuite/affine/widgets/widget-drag-handle/src/watchers/drag-event-watcher.ts @@ -1624,7 +1624,7 @@ export class DragEventWatcher { disposables.add(this._monitorBlockDrag()); disposables.add( - std.view.viewUpdated.on(payload => { + std.view.viewUpdated.subscribe(payload => { if (payload.type !== 'block') { return; } diff --git a/blocksuite/affine/widgets/widget-drag-handle/src/watchers/edgeless-watcher.ts b/blocksuite/affine/widgets/widget-drag-handle/src/watchers/edgeless-watcher.ts index dd42d8613f..70f6bc1680 100644 --- a/blocksuite/affine/widgets/widget-drag-handle/src/watchers/edgeless-watcher.ts +++ b/blocksuite/affine/widgets/widget-drag-handle/src/watchers/edgeless-watcher.ts @@ -177,23 +177,23 @@ export class EdgelessWatcher { const edgelessSlots = std.get(EdgelessLegacySlotIdentifier); disposables.add( - viewport.viewportUpdated.on(this._handleEdgelessViewPortUpdated) + viewport.viewportUpdated.subscribe(this._handleEdgelessViewPortUpdated) ); disposables.add( - selection.slots.updated.on(() => { + selection.slots.updated.subscribe(() => { this.updateAnchorElement(); }) ); disposables.add( - edgelessSlots.readonlyUpdated.on(() => { + edgelessSlots.readonlyUpdated.subscribe(() => { this.updateAnchorElement(); }) ); disposables.add( - edgelessSlots.elementResizeEnd.on(() => { + edgelessSlots.elementResizeEnd.subscribe(() => { this.updateAnchorElement(); }) ); @@ -207,14 +207,14 @@ export class EdgelessWatcher { ); disposables.add( - edgelessSlots.elementResizeStart.on(() => { + edgelessSlots.elementResizeStart.subscribe(() => { this.widget.hide(); }) ); if (surface) { disposables.add( - surface.elementUpdated.on(() => { + surface.elementUpdated.subscribe(() => { if (this.widget.isGfxDragHandleVisible) { this._showDragHandle().catch(console.error); } diff --git a/blocksuite/affine/widgets/widget-drag-handle/src/watchers/page-watcher.ts b/blocksuite/affine/widgets/widget-drag-handle/src/watchers/page-watcher.ts index 761e41069d..465c4da9e7 100644 --- a/blocksuite/affine/widgets/widget-drag-handle/src/watchers/page-watcher.ts +++ b/blocksuite/affine/widgets/widget-drag-handle/src/watchers/page-watcher.ts @@ -13,11 +13,11 @@ export class PageWatcher { const { disposables } = this.widget; disposables.add( - this.widget.doc.slots.blockUpdated.on(() => this.widget.hide()) + this.widget.doc.slots.blockUpdated.subscribe(() => this.widget.hide()) ); disposables.add( - this.pageViewportService.on(() => { + this.pageViewportService.subscribe(() => { this.widget.hide(); }) ); diff --git a/blocksuite/affine/widgets/widget-edgeless-auto-connect/package.json b/blocksuite/affine/widgets/widget-edgeless-auto-connect/package.json index 50159b0779..048c3fa48d 100644 --- a/blocksuite/affine/widgets/widget-edgeless-auto-connect/package.json +++ b/blocksuite/affine/widgets/widget-edgeless-auto-connect/package.json @@ -23,7 +23,8 @@ "@blocksuite/icons": "^2.2.3", "@preact/signals-core": "^1.8.0", "@toeverything/theme": "^1.1.12", - "lit": "^3.2.0" + "lit": "^3.2.0", + "rxjs": "^7.8.1" }, "exports": { ".": "./src/index.ts", diff --git a/blocksuite/affine/widgets/widget-edgeless-auto-connect/src/index.ts b/blocksuite/affine/widgets/widget-edgeless-auto-connect/src/index.ts index 52efed8a7c..41cea4a93b 100644 --- a/blocksuite/affine/widgets/widget-edgeless-auto-connect/src/index.ts +++ b/blocksuite/affine/widgets/widget-edgeless-auto-connect/src/index.ts @@ -305,12 +305,12 @@ export class EdgelessAutoConnectWidget extends WidgetComponent { }; this._disposables.add( - this._selection.slots.updated.on(() => { + this._selection.slots.updated.subscribe(() => { getVisibility(); }) ); this._disposables.add( - this.doc.slots.blockUpdated.on(payload => { + this.doc.slots.blockUpdated.subscribe(payload => { if (payload.flavour === 'affine:surface-ref') { switch (payload.type) { case 'add': @@ -339,7 +339,7 @@ export class EdgelessAutoConnectWidget extends WidgetComponent { const surface = this._gfx.surface; if (surface) { this._disposables.add( - surface.elementUpdated.on(payload => { + surface.elementUpdated.subscribe(payload => { if ( payload.props['xywh'] && surfaceRefs.some(ref => ref.reference === payload.id) @@ -539,13 +539,13 @@ export class EdgelessAutoConnectWidget extends WidgetComponent { const gfx = std.get(GfxControllerIdentifier); _disposables.add( - gfx.viewport.viewportUpdated.on(() => { + gfx.viewport.viewportUpdated.subscribe(() => { this.requestUpdate(); }) ); _disposables.add( - gfx.selection.slots.updated.on(() => { + gfx.selection.slots.updated.subscribe(() => { const { selectedElements } = gfx.selection; if ( !(selectedElements.length === 1 && isNoteBlock(selectedElements[0])) @@ -566,12 +566,12 @@ export class EdgelessAutoConnectWidget extends WidgetComponent { }) ); _disposables.add( - slots.elementResizeStart.on(() => { + slots.elementResizeStart.subscribe(() => { this._dragging = true; }) ); _disposables.add( - slots.elementResizeEnd.on(() => { + slots.elementResizeEnd.subscribe(() => { this._dragging = false; }) ); diff --git a/blocksuite/affine/widgets/widget-frame-title/package.json b/blocksuite/affine/widgets/widget-frame-title/package.json index e62d50eeb8..6d9dff71aa 100644 --- a/blocksuite/affine/widgets/widget-frame-title/package.json +++ b/blocksuite/affine/widgets/widget-frame-title/package.json @@ -21,7 +21,8 @@ "@lit/context": "^1.1.2", "@preact/signals-core": "^1.8.0", "@toeverything/theme": "^1.1.12", - "lit": "^3.2.0" + "lit": "^3.2.0", + "rxjs": "^7.8.1" }, "exports": { ".": "./src/index.ts", diff --git a/blocksuite/affine/widgets/widget-frame-title/src/frame-title.ts b/blocksuite/affine/widgets/widget-frame-title/src/frame-title.ts index 4f29fa9229..c351b41658 100644 --- a/blocksuite/affine/widgets/widget-frame-title/src/frame-title.ts +++ b/blocksuite/affine/widgets/widget-frame-title/src/frame-title.ts @@ -161,7 +161,7 @@ export class AffineFrameTitle extends SignalWatcher( this._nestedFrame = this._isInsideFrame(); _disposables.add( - doc.slots.blockUpdated.on(payload => { + doc.slots.blockUpdated.subscribe(payload => { if ( (payload.type === 'update' && payload.props.key === 'xywh' && @@ -182,14 +182,14 @@ export class AffineFrameTitle extends SignalWatcher( ); _disposables.add( - this.model.propsUpdated.on(() => { + this.model.propsUpdated.subscribe(() => { this._xywh = this.model.xywh; this.requestUpdate(); }) ); _disposables.add( - gfx.selection.slots.updated.on(() => { + gfx.selection.slots.updated.subscribe(() => { this._editing = gfx.selection.selectedIds[0] === this.model.id && gfx.selection.editing; @@ -197,7 +197,7 @@ export class AffineFrameTitle extends SignalWatcher( ); _disposables.add( - gfx.viewport.viewportUpdated.on(({ zoom }) => { + gfx.viewport.viewportUpdated.subscribe(({ zoom }) => { this._zoom = zoom; this.requestUpdate(); }) diff --git a/blocksuite/affine/widgets/widget-remote-selection/package.json b/blocksuite/affine/widgets/widget-remote-selection/package.json index 89c5dc6e7c..1acccfdbfa 100644 --- a/blocksuite/affine/widgets/widget-remote-selection/package.json +++ b/blocksuite/affine/widgets/widget-remote-selection/package.json @@ -24,7 +24,8 @@ "@toeverything/theme": "^1.1.12", "@types/lodash-es": "^4.17.12", "lit": "^3.2.0", - "lodash-es": "^4.17.21" + "lodash-es": "^4.17.21", + "rxjs": "^7.8.1" }, "exports": { ".": "./src/index.ts", diff --git a/blocksuite/affine/widgets/widget-remote-selection/src/doc/doc-remote-selection.ts b/blocksuite/affine/widgets/widget-remote-selection/src/doc/doc-remote-selection.ts index aa13530a4a..c6ee41762d 100644 --- a/blocksuite/affine/widgets/widget-remote-selection/src/doc/doc-remote-selection.ts +++ b/blocksuite/affine/widgets/widget-remote-selection/src/doc/doc-remote-selection.ts @@ -303,14 +303,14 @@ export class AffineDocRemoteSelectionWidget extends WidgetComponent { ); this.disposables.add( - this.std.store.slots.blockUpdated.on(() => { + this.std.store.slots.blockUpdated.subscribe(() => { this._updateSelectionsThrottled(this._remoteSelections.peek()); }) ); const gfx = this.std.get(GfxControllerIdentifier); this.disposables.add( - gfx.viewport.viewportUpdated.on(() => { + gfx.viewport.viewportUpdated.subscribe(() => { const selections = this._remoteSelections.peek(); this._updateSelections(selections); }) diff --git a/blocksuite/affine/widgets/widget-remote-selection/src/edgeless/index.ts b/blocksuite/affine/widgets/widget-remote-selection/src/edgeless/index.ts index 04a71f0c93..90216a33e4 100644 --- a/blocksuite/affine/widgets/widget-remote-selection/src/edgeless/index.ts +++ b/blocksuite/affine/widgets/widget-remote-selection/src/edgeless/index.ts @@ -184,27 +184,31 @@ export class EdgelessRemoteSelectionWidget extends WidgetComponent { + this.selection.slots.remoteUpdated.subscribe(this._updateRemoteRects) + ); + _disposables.add( + this.selection.slots.remoteCursorUpdated.subscribe( + this._updateRemoteCursor + ) + ); + + _disposables.add( + this.gfx.viewport.viewportUpdated.subscribe(() => { this._updateTransform(); }) ); diff --git a/blocksuite/affine/widgets/widget-scroll-anchoring/package.json b/blocksuite/affine/widgets/widget-scroll-anchoring/package.json index 452720671b..90c0521162 100644 --- a/blocksuite/affine/widgets/widget-scroll-anchoring/package.json +++ b/blocksuite/affine/widgets/widget-scroll-anchoring/package.json @@ -19,7 +19,8 @@ "@blocksuite/global": "workspace:*", "@preact/signals-core": "^1.8.0", "@toeverything/theme": "^1.1.12", - "lit": "^3.2.0" + "lit": "^3.2.0", + "rxjs": "^7.8.1" }, "exports": { ".": "./src/index.ts", diff --git a/blocksuite/affine/widgets/widget-scroll-anchoring/src/scroll-anchoring.ts b/blocksuite/affine/widgets/widget-scroll-anchoring/src/scroll-anchoring.ts index 9bdb22b215..8371e1d53d 100644 --- a/blocksuite/affine/widgets/widget-scroll-anchoring/src/scroll-anchoring.ts +++ b/blocksuite/affine/widgets/widget-scroll-anchoring/src/scroll-anchoring.ts @@ -102,18 +102,24 @@ export class AffineScrollAnchoringWidget extends WidgetComponent { if (!xywh) { if (!this.#listened) return; - // listen for document updates - this.disposables.add( - this.std.store.slots.blockUpdated - .filter(v => v.type === 'add' && v.id === id) - .once(() => this.#moveToAnchorInEdgeless(id)) - ); + const blockUpdatedSubscription = + this.std.store.slots.blockUpdated.subscribe(v => { + if (v.type === 'add' && v.id === id) { + blockUpdatedSubscription.unsubscribe(); + this.#moveToAnchorInEdgeless(id); + } + }); - this.disposables.add( - surface.elementAdded - .filter(v => v.id === id && v.local === false) - .once(() => this.#moveToAnchorInEdgeless(id)) - ); + const elementAddedSubscription = surface.elementAdded.subscribe(v => { + if (v.id === id && v.local === false) { + elementAddedSubscription.unsubscribe(); + this.#moveToAnchorInEdgeless(id); + } + }); + + // listen for document updates + this.disposables.add(blockUpdatedSubscription); + this.disposables.add(elementAddedSubscription); return; } @@ -152,11 +158,13 @@ export class AffineScrollAnchoringWidget extends WidgetComponent { if (!this.#listened) return; // listen for document updates - this.disposables.add( - this.std.store.slots.blockUpdated - .filter(v => v.type === 'add' && v.id === id) - .once(() => this.#moveToAnchorInPage(id)) - ); + const subscription = this.std.store.slots.blockUpdated.subscribe(v => { + if (v.type === 'add' && v.id === id) { + subscription.unsubscribe(); + this.#moveToAnchorInPage(id); + } + }); + this.disposables.add(subscription); return; } @@ -192,7 +200,7 @@ export class AffineScrollAnchoringWidget extends WidgetComponent { // In edgeless const controler = this.std.get(GfxControllerIdentifier); this.disposables.add( - controler.viewport.viewportUpdated.on(this.#requestUpdateFn) + controler.viewport.viewportUpdated.subscribe(this.#requestUpdateFn) ); this.disposables.add( diff --git a/blocksuite/affine/widgets/widget-slash-menu/package.json b/blocksuite/affine/widgets/widget-slash-menu/package.json index 1ef2d1e5b5..ce235956b7 100644 --- a/blocksuite/affine/widgets/widget-slash-menu/package.json +++ b/blocksuite/affine/widgets/widget-slash-menu/package.json @@ -26,7 +26,8 @@ "@toeverything/theme": "^1.1.12", "@types/lodash-es": "^4.17.12", "lit": "^3.2.0", - "lodash-es": "^4.17.21" + "lodash-es": "^4.17.21", + "rxjs": "^7.8.1" }, "exports": { ".": "./src/index.ts", diff --git a/blocksuite/affine/widgets/widget-slash-menu/src/slash-menu-popover.ts b/blocksuite/affine/widgets/widget-slash-menu/src/slash-menu-popover.ts index e3865cf014..e7f2c2e5d7 100644 --- a/blocksuite/affine/widgets/widget-slash-menu/src/slash-menu-popover.ts +++ b/blocksuite/affine/widgets/widget-slash-menu/src/slash-menu-popover.ts @@ -233,8 +233,11 @@ export class SlashMenu extends WithDisposable(LitElement) { if (isComposition) { this._updateFilteredItems(); } else { - this.inlineEditor.slots.renderComplete.once( - this._updateFilteredItems + const subscription = this.inlineEditor.slots.renderComplete.subscribe( + () => { + subscription.unsubscribe(); + this._updateFilteredItems(); + } ); } }, @@ -251,7 +254,12 @@ export class SlashMenu extends WithDisposable(LitElement) { if (curRange.index < this._startRange.index) { this.abortController.abort(); } - this.inlineEditor.slots.renderComplete.once(this._updateFilteredItems); + const subscription = this.inlineEditor.slots.renderComplete.subscribe( + () => { + subscription.unsubscribe(); + this._updateFilteredItems(); + } + ); }, onAbort: () => this.abortController.abort(), }); diff --git a/blocksuite/affine/widgets/widget-slash-menu/src/widget.ts b/blocksuite/affine/widgets/widget-slash-menu/src/widget.ts index 8d82400f36..07042278b6 100644 --- a/blocksuite/affine/widgets/widget-slash-menu/src/widget.ts +++ b/blocksuite/affine/widgets/widget-slash-menu/src/widget.ts @@ -4,7 +4,7 @@ import { } from '@blocksuite/affine-rich-text'; import type { UIEventStateContext } from '@blocksuite/block-std'; import { TextSelection, WidgetComponent } from '@blocksuite/block-std'; -import { DisposableGroup } from '@blocksuite/global/slot'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { InlineEditor } from '@blocksuite/inline'; import debounce from 'lodash-es/debounce'; @@ -93,8 +93,16 @@ export class AffineSlashMenuWidget extends WidgetComponent { ) => { const inlineRangeApplyCallback = (callback: () => void) => { // the inline ranged updated in compositionEnd event before this event callback - if (isCompositionEnd) callback(); - else inlineEditor.slots.inlineRangeSync.once(callback); + if (isCompositionEnd) { + callback(); + } else { + const subscription = inlineEditor.slots.inlineRangeSync.subscribe( + () => { + subscription.unsubscribe(); + callback(); + } + ); + } }; if (this.block.model.flavour !== 'affine:page') { diff --git a/blocksuite/affine/widgets/widget-toolbar/package.json b/blocksuite/affine/widgets/widget-toolbar/package.json index 7ec927e94f..84079a8b28 100644 --- a/blocksuite/affine/widgets/widget-toolbar/package.json +++ b/blocksuite/affine/widgets/widget-toolbar/package.json @@ -26,7 +26,8 @@ "@toeverything/theme": "^1.1.12", "@types/lodash-es": "^4.17.12", "lit": "^3.2.0", - "lodash-es": "^4.17.21" + "lodash-es": "^4.17.21", + "rxjs": "^7.8.1" }, "exports": { ".": "./src/index.ts", diff --git a/blocksuite/affine/widgets/widget-toolbar/src/toolbar.ts b/blocksuite/affine/widgets/widget-toolbar/src/toolbar.ts index 2495e040ef..64df593e77 100644 --- a/blocksuite/affine/widgets/widget-toolbar/src/toolbar.ts +++ b/blocksuite/affine/widgets/widget-toolbar/src/toolbar.ts @@ -211,7 +211,7 @@ export class AffineToolbarWidget extends WidgetComponent { ); disposables.add( - std.selection.slots.changed.on(selections => { + std.selection.slots.changed.subscribe(selections => { if (!context.activated) return; const value = flags.value$.peek(); @@ -239,26 +239,25 @@ export class AffineToolbarWidget extends WidgetComponent { // When switch the view mode, wait until the view is created // `card view` or `embed view` disposables.add( - std.view.viewUpdated - .filter(view => view.type === 'block') - .on(record => { - if ( - flags.isBlock() && - std.selection - .filter$(BlockSelection) - .peek() - .find(s => s.blockId === record.id) - ) { - if (record.method === 'add') { - flags.refresh(Flag.Block); - } - return; + std.view.viewUpdated.subscribe(record => { + if ( + record.type === 'block' && + flags.isBlock() && + std.selection + .filter$(BlockSelection) + .peek() + .find(s => s.blockId === record.id) + ) { + if (record.method === 'add') { + flags.refresh(Flag.Block); } - }) + return; + } + }) ); disposables.add( - std.store.slots.blockUpdated.on(record => { + std.store.slots.blockUpdated.subscribe(record => { if ( flags.isBlock() && record.type === 'update' && @@ -334,28 +333,30 @@ export class AffineToolbarWidget extends WidgetComponent { // Should update position of notes' toolbar in edgeless disposables.add( - this.std.get(GfxControllerIdentifier).viewport.viewportUpdated.on(() => { - if (!context.activated) return; + this.std + .get(GfxControllerIdentifier) + .viewport.viewportUpdated.subscribe(() => { + if (!context.activated) return; - if (flags.value === Flag.None || flags.check(Flag.Hiding)) { - return; - } + if (flags.value === Flag.None || flags.check(Flag.Hiding)) { + return; + } - if (flags.isText()) { - flags.refresh(Flag.Text); - return; - } + if (flags.isText()) { + flags.refresh(Flag.Text); + return; + } - if (flags.isNative()) { - flags.refresh(Flag.Native); - return; - } + if (flags.isNative()) { + flags.refresh(Flag.Native); + return; + } - if (flags.isBlock()) { - flags.refresh(Flag.Block); - return; - } - }) + if (flags.isBlock()) { + flags.refresh(Flag.Block); + return; + } + }) ); disposables.add( diff --git a/blocksuite/framework/block-std/package.json b/blocksuite/framework/block-std/package.json index ae8b2514b0..4c251530d9 100644 --- a/blocksuite/framework/block-std/package.json +++ b/blocksuite/framework/block-std/package.json @@ -31,6 +31,7 @@ "lodash-es": "^4.17.21", "lz-string": "^1.5.0", "rehype-parse": "^9.0.0", + "rxjs": "^7.8.1", "unified": "^11.0.5", "w3c-keyname": "^2.2.8", "yjs": "^13.6.21", diff --git a/blocksuite/framework/block-std/src/event/control/keyboard.ts b/blocksuite/framework/block-std/src/event/control/keyboard.ts index 95f2cea19d..27d5257b36 100644 --- a/blocksuite/framework/block-std/src/event/control/keyboard.ts +++ b/blocksuite/framework/block-std/src/event/control/keyboard.ts @@ -1,5 +1,5 @@ +import { DisposableGroup } from '@blocksuite/global/disposable'; import { IS_ANDROID, IS_MAC } from '@blocksuite/global/env'; -import { DisposableGroup } from '@blocksuite/global/slot'; import { type UIEventHandler, diff --git a/blocksuite/framework/block-std/src/event/dispatcher.ts b/blocksuite/framework/block-std/src/event/dispatcher.ts index 1b4a43fafa..baf6ff2073 100644 --- a/blocksuite/framework/block-std/src/event/dispatcher.ts +++ b/blocksuite/framework/block-std/src/event/dispatcher.ts @@ -1,5 +1,5 @@ +import { DisposableGroup } from '@blocksuite/global/disposable'; import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; -import { DisposableGroup } from '@blocksuite/global/slot'; import { LifeCycleWatcher } from '../extension/index.js'; import { KeymapIdentifier } from '../identifier.js'; diff --git a/blocksuite/framework/block-std/src/extension/editor-life-cycle.ts b/blocksuite/framework/block-std/src/extension/editor-life-cycle.ts index 250d6305b8..5ef68fccb5 100644 --- a/blocksuite/framework/block-std/src/extension/editor-life-cycle.ts +++ b/blocksuite/framework/block-std/src/extension/editor-life-cycle.ts @@ -1,4 +1,5 @@ -import { DisposableGroup, Slot } from '@blocksuite/global/slot'; +import { DisposableGroup } from '@blocksuite/global/disposable'; +import { Subject } from 'rxjs'; import type { BlockStdScope } from '../scope/block-std-scope'; import { LifeCycleWatcher } from './lifecycle-watcher'; @@ -9,10 +10,10 @@ export class EditorLifeCycleExtension extends LifeCycleWatcher { disposables = new DisposableGroup(); readonly slots = { - created: new Slot(), - mounted: new Slot(), - rendered: new Slot(), - unmounted: new Slot(), + created: new Subject(), + mounted: new Subject(), + rendered: new Subject(), + unmounted: new Subject(), }; constructor(override readonly std: BlockStdScope) { @@ -26,22 +27,22 @@ export class EditorLifeCycleExtension extends LifeCycleWatcher { override created() { super.created(); - this.slots.created.emit(); + this.slots.created.next(); } override mounted() { super.mounted(); - this.slots.mounted.emit(); + this.slots.mounted.next(); } override rendered() { super.rendered(); - this.slots.rendered.emit(); + this.slots.rendered.next(); } override unmounted() { super.unmounted(); - this.slots.unmounted.emit(); + this.slots.unmounted.next(); this.disposables.dispose(); } diff --git a/blocksuite/framework/block-std/src/extension/service.ts b/blocksuite/framework/block-std/src/extension/service.ts index 632a367f7c..fb2d639d2b 100644 --- a/blocksuite/framework/block-std/src/extension/service.ts +++ b/blocksuite/framework/block-std/src/extension/service.ts @@ -1,6 +1,6 @@ import type { Container } from '@blocksuite/global/di'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; -import { DisposableGroup } from '@blocksuite/global/slot'; import { Extension } from '@blocksuite/store'; import type { EventName, UIEventHandler } from '../event/index.js'; @@ -109,12 +109,12 @@ export abstract class BlockService extends Extension { // life cycle end mounted() { - this.specSlots.mounted.emit({ service: this }); + this.specSlots.mounted.next({ service: this }); } unmounted() { this.dispose(); - this.specSlots.unmounted.emit({ service: this }); + this.specSlots.unmounted.next({ service: this }); } // event handlers end } diff --git a/blocksuite/framework/block-std/src/gfx/controller.ts b/blocksuite/framework/block-std/src/gfx/controller.ts index 7e2ae9a12d..db1ab7f58a 100644 --- a/blocksuite/framework/block-std/src/gfx/controller.ts +++ b/blocksuite/framework/block-std/src/gfx/controller.ts @@ -1,10 +1,10 @@ +import { DisposableGroup } from '@blocksuite/global/disposable'; import { Bound, getCommonBound, getCommonBoundWithRotation, type IBound, } from '@blocksuite/global/gfx'; -import { DisposableGroup } from '@blocksuite/global/slot'; import { assertType } from '@blocksuite/global/utils'; import type { BlockModel } from '@blocksuite/store'; import { Signal } from '@preact/signals-core'; diff --git a/blocksuite/framework/block-std/src/gfx/grid.ts b/blocksuite/framework/block-std/src/gfx/grid.ts index 87859c8dab..f2ff064417 100644 --- a/blocksuite/framework/block-std/src/gfx/grid.ts +++ b/blocksuite/framework/block-std/src/gfx/grid.ts @@ -1,10 +1,10 @@ +import { DisposableGroup } from '@blocksuite/global/disposable'; import type { IBound } from '@blocksuite/global/gfx'; import { Bound, getBoundWithRotation, intersects, } from '@blocksuite/global/gfx'; -import { DisposableGroup } from '@blocksuite/global/slot'; import type { BlockModel } from '@blocksuite/store'; import { compare } from '../utils/layer.js'; @@ -385,7 +385,7 @@ export class GridManager extends GfxExtension { }; disposables.add( - store.slots.blockUpdated.on(payload => { + store.slots.blockUpdated.subscribe(payload => { if (payload.type === 'add' && canBeRenderedAsGfxBlock(payload.model)) { this.add(payload.model); } @@ -441,19 +441,19 @@ export class GridManager extends GfxExtension { ); disposables.add( - surface.elementAdded.on(payload => { + surface.elementAdded.subscribe(payload => { this.add(surface.getElementById(payload.id)!); }) ); disposables.add( - surface.elementRemoved.on(payload => { + surface.elementRemoved.subscribe(payload => { this.remove(payload.model); }) ); disposables.add( - surface.elementUpdated.on(payload => { + surface.elementUpdated.subscribe(payload => { if ( payload.props['xywh'] || payload.props['externalXYWH'] || @@ -465,13 +465,13 @@ export class GridManager extends GfxExtension { ); disposables.add( - surface.localElementAdded.on(elm => { + surface.localElementAdded.subscribe(elm => { this.add(elm); }) ); disposables.add( - surface.localElementUpdated.on(payload => { + surface.localElementUpdated.subscribe(payload => { if (payload.props['xywh'] || payload.props['responseExtension']) { this.update(payload.model); } @@ -479,7 +479,7 @@ export class GridManager extends GfxExtension { ); disposables.add( - surface.localElementDeleted.on(elm => { + surface.localElementDeleted.subscribe(elm => { this.remove(elm); }) ); diff --git a/blocksuite/framework/block-std/src/gfx/keyboard.ts b/blocksuite/framework/block-std/src/gfx/keyboard.ts index d4e6065ad5..98459b489d 100644 --- a/blocksuite/framework/block-std/src/gfx/keyboard.ts +++ b/blocksuite/framework/block-std/src/gfx/keyboard.ts @@ -1,4 +1,4 @@ -import { DisposableGroup } from '@blocksuite/global/slot'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { Signal } from '@preact/signals-core'; import type { BlockStdScope } from '../scope/block-std-scope.js'; diff --git a/blocksuite/framework/block-std/src/gfx/layer.ts b/blocksuite/framework/block-std/src/gfx/layer.ts index dd2db94bb2..ae05da5d5b 100644 --- a/blocksuite/framework/block-std/src/gfx/layer.ts +++ b/blocksuite/framework/block-std/src/gfx/layer.ts @@ -1,8 +1,9 @@ +import { DisposableGroup } from '@blocksuite/global/disposable'; import { Bound } from '@blocksuite/global/gfx'; -import { DisposableGroup, Slot } from '@blocksuite/global/slot'; import { assertType } from '@blocksuite/global/utils'; import { generateKeyBetween } from 'fractional-indexing'; import last from 'lodash-es/last'; +import { Subject } from 'rxjs'; import { compare, @@ -101,7 +102,7 @@ export class LayerManager extends GfxExtension { layers: Layer[] = []; slots = { - layerUpdated: new Slot<{ + layerUpdated: new Subject<{ type: 'delete' | 'add' | 'update'; initiatingElement: GfxModel | GfxLocalElementModel; }>(), @@ -588,7 +589,7 @@ export class LayerManager extends GfxExtension { element.childElements.forEach(child => child && this._updateLayer(child)); } this._buildCanvasLayers(); - this.slots.layerUpdated.emit({ + this.slots.layerUpdated.next({ type: 'add', initiatingElement: element, }); @@ -650,7 +651,7 @@ export class LayerManager extends GfxExtension { if (isGroup) { this._reset(); - this.slots.layerUpdated.emit({ + this.slots.layerUpdated.next({ type: 'delete', initiatingElement: element as GfxModel, }); @@ -673,14 +674,14 @@ export class LayerManager extends GfxExtension { this._removeFromLayer(element, deleteType); this._buildCanvasLayers(); - this.slots.layerUpdated.emit({ + this.slots.layerUpdated.next({ type: 'delete', initiatingElement: element, }); } override unmounted() { - this.slots.layerUpdated.dispose(); + this.slots.layerUpdated.complete(); this._disposable.dispose(); } @@ -784,7 +785,7 @@ export class LayerManager extends GfxExtension { ) { if (this._updateLayer(element, props)) { this._buildCanvasLayers(); - this.slots.layerUpdated.emit({ + this.slots.layerUpdated.next({ type: 'update', initiatingElement: element, }); @@ -795,7 +796,7 @@ export class LayerManager extends GfxExtension { const store = this._doc; this._disposable.add( - store.slots.blockUpdated.on(payload => { + store.slots.blockUpdated.subscribe(payload => { if (payload.type === 'add') { const block = store.getBlockById(payload.id)!; @@ -854,34 +855,34 @@ export class LayerManager extends GfxExtension { ); this._disposable.add( - surface.elementAdded.on(payload => + surface.elementAdded.subscribe(payload => this.add(surface.getElementById(payload.id)!) ) ); this._disposable.add( - surface.elementUpdated.on(payload => { + surface.elementUpdated.subscribe(payload => { if (payload.props['index'] || payload.props['childIds']) { this.update(surface.getElementById(payload.id)!, payload.props); } }) ); this._disposable.add( - surface.elementRemoved.on(payload => this.delete(payload.model!)) + surface.elementRemoved.subscribe(payload => this.delete(payload.model!)) ); this._disposable.add( - surface.localElementAdded.on(elm => { + surface.localElementAdded.subscribe(elm => { this.add(elm); }) ); this._disposable.add( - surface.localElementUpdated.on(payload => { + surface.localElementUpdated.subscribe(payload => { if (payload.props['index'] || payload.props['groupId']) { this.update(payload.model, payload.props); } }) ); this._disposable.add( - surface.localElementDeleted.on(elm => { + surface.localElementDeleted.subscribe(elm => { this.delete(elm); }) ); diff --git a/blocksuite/framework/block-std/src/gfx/model/surface/decorators/watch.ts b/blocksuite/framework/block-std/src/gfx/model/surface/decorators/watch.ts index aa87c37bc6..836a400d95 100644 --- a/blocksuite/framework/block-std/src/gfx/model/surface/decorators/watch.ts +++ b/blocksuite/framework/block-std/src/gfx/model/surface/decorators/watch.ts @@ -39,7 +39,7 @@ function startWatch(prop: string | symbol, receiver: GfxPrimitiveElementModel) { if (!watchFn) return; receiver['_disposable'].add( - receiver.surface.elementUpdated.on(payload => { + receiver.surface.elementUpdated.subscribe(payload => { if (payload.id === receiver.id && prop in payload.props) { watchFn(payload.oldValues[prop as string], receiver, payload.local); } diff --git a/blocksuite/framework/block-std/src/gfx/model/surface/element-model.ts b/blocksuite/framework/block-std/src/gfx/model/surface/element-model.ts index 04b8dce6ee..c386462695 100644 --- a/blocksuite/framework/block-std/src/gfx/model/surface/element-model.ts +++ b/blocksuite/framework/block-std/src/gfx/model/surface/element-model.ts @@ -1,3 +1,4 @@ +import { DisposableGroup } from '@blocksuite/global/disposable'; import { Bound, deserializeXYWH, @@ -13,9 +14,9 @@ import { type SerializedXYWH, type XYWH, } from '@blocksuite/global/gfx'; -import { DisposableGroup, Slot } from '@blocksuite/global/slot'; import { createMutex } from 'lib0/mutex'; import isEqual from 'lodash-es/isEqual'; +import { Subject } from 'rxjs'; import * as Y from 'yjs'; import { @@ -86,7 +87,7 @@ export abstract class GfxPrimitiveElementModel< protected _stashed: Map; - propsUpdated = new Slot<{ key: string }>(); + propsUpdated = new Subject<{ key: string }>(); abstract rotate: number; @@ -262,7 +263,7 @@ export abstract class GfxPrimitiveElementModel< onDestroyed() { this._disposable.dispose(); - this.propsUpdated.dispose(); + this.propsUpdated.complete(); } pop(prop: keyof Props | string) { diff --git a/blocksuite/framework/block-std/src/gfx/model/surface/local-element-model.ts b/blocksuite/framework/block-std/src/gfx/model/surface/local-element-model.ts index e09773b2b2..aebea0caa8 100644 --- a/blocksuite/framework/block-std/src/gfx/model/surface/local-element-model.ts +++ b/blocksuite/framework/block-std/src/gfx/model/surface/local-element-model.ts @@ -142,7 +142,7 @@ export abstract class GfxLocalElementModel implements GfxCompatibleInterface { if (surfaceModel.localElementModels.has(p)) { this._mutex(() => { - surfaceModel.localElementUpdated.emit({ + surfaceModel.localElementUpdated.next({ model: p, props: { [prop as string]: value, diff --git a/blocksuite/framework/block-std/src/gfx/model/surface/surface-model.ts b/blocksuite/framework/block-std/src/gfx/model/surface/surface-model.ts index 5bb87dd2d5..83cd499ca2 100644 --- a/blocksuite/framework/block-std/src/gfx/model/surface/surface-model.ts +++ b/blocksuite/framework/block-std/src/gfx/model/surface/surface-model.ts @@ -1,8 +1,9 @@ -import { DisposableGroup, Slot } from '@blocksuite/global/slot'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { assertType, type Constructor } from '@blocksuite/global/utils'; import type { Boxed } from '@blocksuite/store'; import { BlockModel, nanoid } from '@blocksuite/store'; import { signal } from '@preact/signals-core'; +import { Subject } from 'rxjs'; import * as Y from 'yjs'; import { @@ -77,24 +78,24 @@ export class SurfaceBlockModel extends BlockModel { protected _surfaceBlockModel = true; - elementAdded = new Slot<{ id: string; local: boolean }>(); + protected localElements = new Set(); - elementRemoved = new Slot<{ + elementAdded = new Subject<{ id: string; local: boolean }>(); + + elementRemoved = new Subject<{ id: string; type: string; model: GfxPrimitiveElementModel; local: boolean; }>(); - elementUpdated = new Slot(); + elementUpdated = new Subject(); - localElementAdded = new Slot(); + localElementAdded = new Subject(); - localElementDeleted = new Slot(); + localElementDeleted = new Subject(); - protected localElements = new Set(); - - localElementUpdated = new Slot<{ + localElementUpdated = new Subject<{ model: GfxLocalElementModel; props: Record; oldValues: Record; @@ -122,7 +123,10 @@ export class SurfaceBlockModel extends BlockModel { constructor() { super(); - this.created.once(() => this._init()); + const subscription = this.created.subscribe(() => { + this._init(); + subscription.unsubscribe(); + }); } private _createElementFromProps( @@ -296,9 +300,9 @@ export class SurfaceBlockModel extends BlockModel { element, { onChange: payload => { - this.elementUpdated.emit(payload); + this.elementUpdated.next(payload); Object.keys(payload.props).forEach(key => { - model.model.propsUpdated.emit({ key }); + model.model.propsUpdated.next({ key }); }); }, skipFieldInit: true, @@ -323,11 +327,11 @@ export class SurfaceBlockModel extends BlockModel { addedElements.forEach(({ mount, model }) => { mount(); - this.elementAdded.emit({ id: model.id, local: transaction.local }); + this.elementAdded.next({ id: model.id, local: transaction.local }); }); deletedElements.forEach(({ unmount, model }) => { unmount(); - this.elementRemoved.emit({ + this.elementRemoved.next({ id: model.id, type: model.type, model, @@ -343,9 +347,9 @@ export class SurfaceBlockModel extends BlockModel { val, { onChange: payload => { - this.elementUpdated.emit(payload), + this.elementUpdated.next(payload), Object.keys(payload.props).forEach(key => { - model.model.propsUpdated.emit({ key }); + model.model.propsUpdated.next({ key }); }); }, skipFieldInit: true, @@ -368,7 +372,7 @@ export class SurfaceBlockModel extends BlockModel { elementsYMap.observe(onElementsMapChange); - const disposable = this.doc.slots.blockUpdated.on(payload => { + const subscription = this.doc.slots.blockUpdated.subscribe(payload => { switch (payload.type) { case 'add': if (isGfxGroupCompatibleModel(payload.model)) { @@ -392,9 +396,9 @@ export class SurfaceBlockModel extends BlockModel { } }); - this.deleted.on(() => { + this.deleted.subscribe(() => { elementsYMap.unobserve(onElementsMapChange); - disposable.dispose(); + subscription.unsubscribe(); }); } @@ -435,7 +439,7 @@ export class SurfaceBlockModel extends BlockModel { ): element is GfxGroupLikeElementModel => element instanceof GfxGroupLikeElementModel; - const disposable = this.elementUpdated.on(({ id, oldValues }) => { + const disposable = this.elementUpdated.subscribe(({ id, oldValues }) => { const element = this.getElementById(id)!; if ( @@ -446,8 +450,8 @@ export class SurfaceBlockModel extends BlockModel { this.deleteElement(id); } }); - this.deleted.on(() => { - disposable.dispose(); + this.deleted.subscribe(() => { + disposable.unsubscribe(); }); } @@ -458,14 +462,14 @@ export class SurfaceBlockModel extends BlockModel { }; const disposables = new DisposableGroup(); - disposables.add(this.elementAdded.on(updateIsEmpty)); - disposables.add(this.elementRemoved.on(updateIsEmpty)); - this.doc.slots.blockUpdated.on(payload => { + disposables.add(this.elementAdded.subscribe(updateIsEmpty)); + disposables.add(this.elementRemoved.subscribe(updateIsEmpty)); + this.doc.slots.blockUpdated.subscribe(payload => { if (['add', 'delete'].includes(payload.type)) { updateIsEmpty(); } }); - this.deleted.on(() => { + this.deleted.subscribe(() => { disposables.dispose(); }); } @@ -518,9 +522,9 @@ export class SurfaceBlockModel extends BlockModel { const elementModel = this._createElementFromProps(props, { onChange: payload => { - this.elementUpdated.emit(payload); + this.elementUpdated.next(payload); Object.keys(payload.props).forEach(key => { - elementModel.model.propsUpdated.emit({ key }); + elementModel.model.propsUpdated.next({ key }); }); }, }); @@ -536,7 +540,7 @@ export class SurfaceBlockModel extends BlockModel { addLocalElement(elem: GfxLocalElementModel) { this.localElements.add(elem); - this.localElementAdded.emit(elem); + this.localElementAdded.next(elem); } applyMiddlewares(middlewares: SurfaceMiddleware[]) { @@ -575,16 +579,16 @@ export class SurfaceBlockModel extends BlockModel { deleteLocalElement(elem: GfxLocalElementModel) { if (this.localElements.delete(elem)) { - this.localElementDeleted.emit(elem); + this.localElementDeleted.next(elem); } } override dispose(): void { super.dispose(); - this.elementAdded.dispose(); - this.elementRemoved.dispose(); - this.elementUpdated.dispose(); + this.elementAdded.complete(); + this.elementRemoved.complete(); + this.elementUpdated.complete(); this._elementModels.forEach(({ unmount }) => unmount()); this._elementModels.clear(); diff --git a/blocksuite/framework/block-std/src/gfx/selection.ts b/blocksuite/framework/block-std/src/gfx/selection.ts index 8f12ed2bb1..24973a0cf7 100644 --- a/blocksuite/framework/block-std/src/gfx/selection.ts +++ b/blocksuite/framework/block-std/src/gfx/selection.ts @@ -1,10 +1,11 @@ +import { DisposableGroup } from '@blocksuite/global/disposable'; import { getCommonBoundWithRotation, type IPoint, } from '@blocksuite/global/gfx'; -import { DisposableGroup, Slot } from '@blocksuite/global/slot'; import { assertType } from '@blocksuite/global/utils'; import groupBy from 'lodash-es/groupBy'; +import { Subject } from 'rxjs'; import { BlockSelection, @@ -60,11 +61,11 @@ export class GfxSelectionManager extends GfxExtension { disposable: DisposableGroup = new DisposableGroup(); readonly slots = { - updated: new Slot(), - remoteUpdated: new Slot(), + updated: new Subject(), + remoteUpdated: new Subject(), - cursorUpdated: new Slot(), - remoteCursorUpdated: new Slot(), + cursorUpdated: new Subject(), + remoteCursorUpdated: new Subject(), }; get activeGroup() { @@ -217,7 +218,7 @@ export class GfxSelectionManager extends GfxExtension { override mounted() { this.disposable.add( - this.stdSelection.slots.changed.on(selections => { + this.stdSelection.slots.changed.subscribe(selections => { const { cursor = [], surface = [] } = groupBy(selections, sel => { if (sel.is(SurfaceSelection)) { return 'surface'; @@ -233,7 +234,7 @@ export class GfxSelectionManager extends GfxExtension { if (cursor[0] && !this.cursorSelection?.equals(cursor[0])) { this._cursorSelection = cursor[0]; - this.slots.cursorUpdated.emit(cursor[0]); + this.slots.cursorUpdated.next(cursor[0]); } if ((surface.length === 0 && this.empty) || this.equals(surface)) { @@ -250,12 +251,12 @@ export class GfxSelectionManager extends GfxExtension { }) ); - this.slots.updated.emit(this.surfaceSelections); + this.slots.updated.next(this.surfaceSelections); }) ); this.disposable.add( - this.stdSelection.slots.remoteChanged.on(states => { + this.stdSelection.slots.remoteChanged.subscribe(states => { const surfaceMap = new Map(); const cursorMap = new Map(); const selectedSet = new Set(); @@ -299,8 +300,8 @@ export class GfxSelectionManager extends GfxExtension { this._remoteSurfaceSelectionsMap = surfaceMap; this._remoteSelectedSet = selectedSet; - this.slots.remoteUpdated.emit(); - this.slots.remoteCursorUpdated.emit(); + this.slots.remoteUpdated.next(); + this.slots.remoteCursorUpdated.next(); }) ); } diff --git a/blocksuite/framework/block-std/src/gfx/tool/tool-controller.ts b/blocksuite/framework/block-std/src/gfx/tool/tool-controller.ts index 2a8486e8bb..7c31b6d190 100644 --- a/blocksuite/framework/block-std/src/gfx/tool/tool-controller.ts +++ b/blocksuite/framework/block-std/src/gfx/tool/tool-controller.ts @@ -1,8 +1,9 @@ import type { ServiceIdentifier } from '@blocksuite/global/di'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; import type { IBound, IPoint } from '@blocksuite/global/gfx'; -import { DisposableGroup, Slot } from '@blocksuite/global/slot'; import { Signal } from '@preact/signals-core'; +import { Subject } from 'rxjs'; import type { PointerEventState } from '../../event/index.js'; import type { GfxController } from '../controller.js'; @@ -79,7 +80,7 @@ export const eventTarget = Symbol('eventTarget'); export class ToolController extends GfxExtension { static override key = 'ToolController'; - private readonly _builtInHookSlot = new Slot(); + private readonly _builtInHookSlot = new Subject(); private readonly _disposableGroup = new DisposableGroup(); @@ -441,7 +442,7 @@ export class ToolController extends GfxExtension { ); }); - this._builtInHookSlot.on(evt => { + this._builtInHookSlot.subscribe(evt => { hooks[evt.event]?.forEach(hook => hook(evt)); }); @@ -499,7 +500,7 @@ export class ToolController extends GfxExtension { const beforeUpdateCtx = this._createBuiltInHookCtx('beforeToolUpdate', { toolName: toolNameStr, }); - this._builtInHookSlot.emit(beforeUpdateCtx.slotCtx); + this._builtInHookSlot.next(beforeUpdateCtx.slotCtx); if (beforeUpdateCtx.prevented) { return; @@ -528,7 +529,7 @@ export class ToolController extends GfxExtension { const afterUpdateCtx = this._createBuiltInHookCtx('toolUpdate', { toolName: toolNameStr, }); - this._builtInHookSlot.emit(afterUpdateCtx.slotCtx); + this._builtInHookSlot.next(afterUpdateCtx.slotCtx); } override unmounted(): void { @@ -537,7 +538,7 @@ export class ToolController extends GfxExtension { tool.unmounted(); tool['disposable'].dispose(); }); - this._builtInHookSlot.dispose(); + this._builtInHookSlot.complete(); } } diff --git a/blocksuite/framework/block-std/src/gfx/tool/tool.ts b/blocksuite/framework/block-std/src/gfx/tool/tool.ts index 2e0e1581a3..e86bc0ff7b 100644 --- a/blocksuite/framework/block-std/src/gfx/tool/tool.ts +++ b/blocksuite/framework/block-std/src/gfx/tool/tool.ts @@ -1,6 +1,6 @@ import { type Container, createIdentifier } from '@blocksuite/global/di'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; -import { DisposableGroup } from '@blocksuite/global/slot'; import { Extension } from '@blocksuite/store'; import type { PointerEventState } from '../../event/index.js'; diff --git a/blocksuite/framework/block-std/src/gfx/view/view-manager.ts b/blocksuite/framework/block-std/src/gfx/view/view-manager.ts index 341b7feb51..70078c163d 100644 --- a/blocksuite/framework/block-std/src/gfx/view/view-manager.ts +++ b/blocksuite/framework/block-std/src/gfx/view/view-manager.ts @@ -1,4 +1,4 @@ -import { DisposableGroup } from '@blocksuite/global/slot'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { onSurfaceAdded } from '../../utils/gfx.js'; import type { GfxController } from '../controller.js'; @@ -70,14 +70,14 @@ export class ViewManager extends GfxExtension { }; this._disposable.add( - surface.elementAdded.on(payload => { + surface.elementAdded.subscribe(payload => { const model = surface.getElementById(payload.id)!; createView(model); }) ); this._disposable.add( - surface.elementRemoved.on(elem => { + surface.elementRemoved.subscribe(elem => { const view = this._viewMap.get(elem.id); this._viewMap.delete(elem.id); view?.onDestroyed(); @@ -85,13 +85,13 @@ export class ViewManager extends GfxExtension { ); this._disposable.add( - surface.localElementAdded.on(model => { + surface.localElementAdded.subscribe(model => { createView(model); }) ); this._disposable.add( - surface.localElementDeleted.on(model => { + surface.localElementDeleted.subscribe(model => { const view = this._viewMap.get(model.id); this._viewMap.delete(model.id); view?.onDestroyed(); diff --git a/blocksuite/framework/block-std/src/gfx/view/view.ts b/blocksuite/framework/block-std/src/gfx/view/view.ts index b851863976..3b934158ae 100644 --- a/blocksuite/framework/block-std/src/gfx/view/view.ts +++ b/blocksuite/framework/block-std/src/gfx/view/view.ts @@ -1,7 +1,7 @@ import { type Container, createIdentifier } from '@blocksuite/global/di'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; import type { Bound, IVec } from '@blocksuite/global/gfx'; -import { DisposableGroup } from '@blocksuite/global/slot'; import type { Extension } from '@blocksuite/store'; import type { PointerEventState } from '../../event/index.js'; diff --git a/blocksuite/framework/block-std/src/gfx/viewport-element.ts b/blocksuite/framework/block-std/src/gfx/viewport-element.ts index ff6bd6d097..1ecdac9979 100644 --- a/blocksuite/framework/block-std/src/gfx/viewport-element.ts +++ b/blocksuite/framework/block-std/src/gfx/viewport-element.ts @@ -131,10 +131,10 @@ export class GfxViewportElement extends WithDisposable(ShadowlessElement) { this._hideOutsideBlock(); this.disposables.add( - this.viewport.viewportUpdated.on(() => viewportUpdateCallback()) + this.viewport.viewportUpdated.subscribe(() => viewportUpdateCallback()) ); this.disposables.add( - this.viewport.sizeUpdated.on(() => viewportUpdateCallback()) + this.viewport.sizeUpdated.subscribe(() => viewportUpdateCallback()) ); } diff --git a/blocksuite/framework/block-std/src/gfx/viewport.ts b/blocksuite/framework/block-std/src/gfx/viewport.ts index b0587e28a4..59190e73c6 100644 --- a/blocksuite/framework/block-std/src/gfx/viewport.ts +++ b/blocksuite/framework/block-std/src/gfx/viewport.ts @@ -5,9 +5,9 @@ import { type IVec, Vec, } from '@blocksuite/global/gfx'; -import { Slot } from '@blocksuite/global/slot'; import { signal } from '@preact/signals-core'; import debounce from 'lodash-es/debounce'; +import { Subject } from 'rxjs'; import type { GfxViewportElement } from '.'; @@ -74,18 +74,18 @@ export class Viewport { protected _zoom: number = 1.0; - elementReady = new Slot(); + elementReady = new Subject(); - sizeUpdated = new Slot<{ + sizeUpdated = new Subject<{ width: number; height: number; left: number; top: number; }>(); - viewportMoved = new Slot(); + viewportMoved = new Subject(); - viewportUpdated = new Slot<{ + viewportUpdated = new Subject<{ zoom: number; center: IVec; }>(); @@ -106,7 +106,10 @@ export class Viewport { }, 200); constructor() { - this.elementReady.once(el => (this._element = el)); + const subscription = this.elementReady.subscribe(el => { + this._element = el; + subscription.unsubscribe(); + }); } get boundingClientRect() { @@ -233,9 +236,9 @@ export class Viewport { dispose() { this.clearViewportElement(); - this.sizeUpdated.dispose(); - this.viewportMoved.dispose(); - this.viewportUpdated.dispose(); + this.sizeUpdated.complete(); + this.viewportMoved.complete(); + this.viewportUpdated.complete(); this.zooming$.value = false; this.panning$.value = false; } @@ -296,7 +299,7 @@ export class Viewport { this._center.x = centerX; this._center.y = centerY; this.panning$.value = true; - this.viewportUpdated.emit({ + this.viewportUpdated.next({ zoom: this.zoom, center: Vec.toVec(this.center) as IVec, }); @@ -306,7 +309,7 @@ export class Viewport { setRect(left: number, top: number, width: number, height: number) { this._left = left; this._top = top; - this.sizeUpdated.emit({ + this.sizeUpdated.next({ left, top, width, @@ -420,7 +423,7 @@ export class Viewport { this.zooming$.value = true; } this.setCenter(newCenter[0], newCenter[1]); - this.viewportUpdated.emit({ + this.viewportUpdated.next({ zoom: this.zoom, center: Vec.toVec(this.center) as IVec, }); diff --git a/blocksuite/framework/block-std/src/range/inline-range-provider.ts b/blocksuite/framework/block-std/src/range/inline-range-provider.ts index 50cde7a888..1d2dd51d60 100644 --- a/blocksuite/framework/block-std/src/range/inline-range-provider.ts +++ b/blocksuite/framework/block-std/src/range/inline-range-provider.ts @@ -87,7 +87,7 @@ export const getInlineRangeProvider: ( const inlineRange$: InlineRangeProvider['inlineRange$'] = signal(null); editorHost.disposables.add( - selectionManager.slots.changed.on(selections => { + selectionManager.slots.changed.subscribe(selections => { if (!isActiveInEditor(editorHost)) return; const textSelection = selections.find(s => s.type === 'text') as diff --git a/blocksuite/framework/block-std/src/range/range-binding.ts b/blocksuite/framework/block-std/src/range/range-binding.ts index f0d7ecbffe..8e48b13b2b 100644 --- a/blocksuite/framework/block-std/src/range/range-binding.ts +++ b/blocksuite/framework/block-std/src/range/range-binding.ts @@ -313,7 +313,7 @@ export class RangeBinding { constructor(public manager: RangeManager) { this.host.disposables.add( - this.selectionManager.slots.changed.on(this._onStdSelectionChanged) + this.selectionManager.slots.changed.subscribe(this._onStdSelectionChanged) ); this.host.disposables.addFromEvent( diff --git a/blocksuite/framework/block-std/src/spec/slots.ts b/blocksuite/framework/block-std/src/spec/slots.ts index 63b75b7931..044756928e 100644 --- a/blocksuite/framework/block-std/src/spec/slots.ts +++ b/blocksuite/framework/block-std/src/spec/slots.ts @@ -1,15 +1,15 @@ -import { Slot } from '@blocksuite/global/slot'; +import { Subject } from 'rxjs'; import type { BlockService } from '../extension/service.js'; import type { BlockComponent, WidgetComponent } from '../view/index.js'; export type BlockSpecSlots = { - mounted: Slot<{ service: Service }>; - unmounted: Slot<{ service: Service }>; - viewConnected: Slot<{ component: BlockComponent; service: Service }>; - viewDisconnected: Slot<{ component: BlockComponent; service: Service }>; - widgetConnected: Slot<{ component: WidgetComponent; service: Service }>; - widgetDisconnected: Slot<{ + mounted: Subject<{ service: Service }>; + unmounted: Subject<{ service: Service }>; + viewConnected: Subject<{ component: BlockComponent; service: Service }>; + viewDisconnected: Subject<{ component: BlockComponent; service: Service }>; + widgetConnected: Subject<{ component: WidgetComponent; service: Service }>; + widgetDisconnected: Subject<{ component: WidgetComponent; service: Service; }>; @@ -17,11 +17,11 @@ export type BlockSpecSlots = { export const getSlots = (): BlockSpecSlots => { return { - mounted: new Slot(), - unmounted: new Slot(), - viewConnected: new Slot(), - viewDisconnected: new Slot(), - widgetConnected: new Slot(), - widgetDisconnected: new Slot(), + mounted: new Subject(), + unmounted: new Subject(), + viewConnected: new Subject(), + viewDisconnected: new Subject(), + widgetConnected: new Subject(), + widgetDisconnected: new Subject(), }; }; diff --git a/blocksuite/framework/block-std/src/view/element/block-component.ts b/blocksuite/framework/block-std/src/view/element/block-component.ts index d226402afa..e01685686e 100644 --- a/blocksuite/framework/block-std/src/view/element/block-component.ts +++ b/blocksuite/framework/block-std/src/view/element/block-component.ts @@ -214,21 +214,23 @@ export class BlockComponent< this.std.view.setBlock(this); - const disposable = this.std.store.slots.blockUpdated.on(({ type, id }) => { - if (id === this.model.id && type === 'delete') { - this.std.view.deleteBlock(this); - disposable.dispose(); + const disposable = this.std.store.slots.blockUpdated.subscribe( + ({ type, id }) => { + if (id === this.model.id && type === 'delete') { + this.std.view.deleteBlock(this); + disposable.unsubscribe(); + } } - }); + ); this._disposables.add(disposable); this._disposables.add( - this.model.propsUpdated.on(() => { + this.model.propsUpdated.subscribe(() => { this.requestUpdate(); }) ); - this.service?.specSlots.viewConnected.emit({ + this.service?.specSlots.viewConnected.next({ service: this.service, component: this, }); @@ -237,7 +239,7 @@ export class BlockComponent< override disconnectedCallback() { super.disconnectedCallback(); - this.service?.specSlots.viewDisconnected.emit({ + this.service?.specSlots.viewDisconnected.next({ service: this.service, component: this, }); diff --git a/blocksuite/framework/block-std/src/view/element/gfx-block-component.ts b/blocksuite/framework/block-std/src/view/element/gfx-block-component.ts index bebbbfc2ab..7b0563a078 100644 --- a/blocksuite/framework/block-std/src/view/element/gfx-block-component.ts +++ b/blocksuite/framework/block-std/src/view/element/gfx-block-component.ts @@ -30,13 +30,13 @@ function handleGfxConnection(instance: GfxBlockComponent) { instance.style.position = 'absolute'; instance.disposables.add( - instance.gfx.viewport.viewportUpdated.on(() => { + instance.gfx.viewport.viewportUpdated.subscribe(() => { updateTransform(instance); }) ); instance.disposables.add( - instance.doc.slots.blockUpdated.on(({ type, id }) => { + instance.doc.slots.blockUpdated.subscribe(({ type, id }) => { if (id === instance.model.id && type === 'update') { updateTransform(instance); } diff --git a/blocksuite/framework/block-std/src/view/element/widget-component.ts b/blocksuite/framework/block-std/src/view/element/widget-component.ts index 5a390ef8f0..8121f5405d 100644 --- a/blocksuite/framework/block-std/src/view/element/widget-component.ts +++ b/blocksuite/framework/block-std/src/view/element/widget-component.ts @@ -74,7 +74,7 @@ export class WidgetComponent< super.connectedCallback(); this.std.view.setWidget(this); - this.service?.specSlots.widgetConnected.emit({ + this.service?.specSlots.widgetConnected.next({ service: this.service, component: this, }); @@ -83,7 +83,7 @@ export class WidgetComponent< override disconnectedCallback() { super.disconnectedCallback(); this.std?.view.deleteWidget(this); - this.service?.specSlots.widgetDisconnected.emit({ + this.service?.specSlots.widgetDisconnected.next({ service: this.service, component: this, }); diff --git a/blocksuite/framework/block-std/src/view/view-store.ts b/blocksuite/framework/block-std/src/view/view-store.ts index d0b41907fa..e2efaf3f3a 100644 --- a/blocksuite/framework/block-std/src/view/view-store.ts +++ b/blocksuite/framework/block-std/src/view/view-store.ts @@ -1,4 +1,4 @@ -import { Slot } from '@blocksuite/global/slot'; +import { Subject } from 'rxjs'; import { LifeCycleWatcher } from '../extension/index.js'; import type { BlockComponent, WidgetComponent } from './element/index.js'; @@ -24,7 +24,7 @@ export class ViewStore extends LifeCycleWatcher { private readonly _blockMap = new Map(); - viewUpdated: Slot = new Slot(); + viewUpdated: Subject = new Subject(); get views() { return Array.from(this._blockMap.values()); @@ -44,7 +44,7 @@ export class ViewStore extends LifeCycleWatcher { deleteBlock = (node: BlockComponent) => { this._blockMap.delete(node.model.id); - this.viewUpdated.emit({ + this.viewUpdated.next({ id: node.model.id, method: 'delete', type: 'block', @@ -56,7 +56,7 @@ export class ViewStore extends LifeCycleWatcher { const id = node.dataset.widgetId as string; const widgetIndex = `${node.model.id}|${id}`; this._widgetMap.delete(widgetIndex); - this.viewUpdated.emit({ + this.viewUpdated.next({ id: node.model.id, method: 'delete', type: 'widget', @@ -81,7 +81,7 @@ export class ViewStore extends LifeCycleWatcher { this.deleteBlock(node); } this._blockMap.set(node.model.id, node); - this.viewUpdated.emit({ + this.viewUpdated.next({ id: node.model.id, method: 'add', type: 'block', @@ -93,7 +93,7 @@ export class ViewStore extends LifeCycleWatcher { const id = node.dataset.widgetId as string; const widgetIndex = `${node.model.id}|${id}`; this._widgetMap.set(widgetIndex, node); - this.viewUpdated.emit({ + this.viewUpdated.next({ id: node.model.id, method: 'add', type: 'widget', @@ -140,5 +140,6 @@ export class ViewStore extends LifeCycleWatcher { override unmounted() { this._blockMap.clear(); this._widgetMap.clear(); + this.viewUpdated.complete(); } } diff --git a/blocksuite/framework/global/package.json b/blocksuite/framework/global/package.json index d92435c265..dd649ebc7d 100644 --- a/blocksuite/framework/global/package.json +++ b/blocksuite/framework/global/package.json @@ -17,7 +17,7 @@ "./di": "./src/di/index.ts", "./types": "./src/types/index.ts", "./gfx": "./src/gfx/index.ts", - "./slot": "./src/slot/index.ts", + "./disposable": "./src/disposable/index.ts", "./lit": "./src/lit/index.ts" }, "typesVersions": { @@ -40,8 +40,8 @@ "gfx": [ "dist/gfx/index.d.ts" ], - "slot": [ - "dist/slot/index.d.ts" + "disposable": [ + "dist/disposable/index.d.ts" ], "lit": [ "dist/lit/index.d.ts" @@ -61,6 +61,7 @@ "@preact/signals-core": "^1.8.0", "lib0": "^0.2.97", "lit": "^3.2.0", + "rxjs": "^7.8.1", "zod": "^3.23.8" }, "devDependencies": { diff --git a/blocksuite/framework/global/src/__tests__/slot.unit.spec.ts b/blocksuite/framework/global/src/__tests__/slot.unit.spec.ts deleted file mode 100644 index 1db9fee9dd..0000000000 --- a/blocksuite/framework/global/src/__tests__/slot.unit.spec.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { describe, expect, test, vi } from 'vitest'; - -import { Slot } from '../slot/slot.js'; - -describe('slot', () => { - test('init', () => { - const slot = new Slot(); - expect(slot).is.toBeDefined(); - }); - - test('emit', () => { - const slot = new Slot(); - const callback = vi.fn(); - slot.on(callback); - slot.emit(); - expect(callback).toBeCalled(); - }); - - test('emit with value', () => { - const slot = new Slot(); - const callback = vi.fn(v => expect(v).toBe(5)); - slot.on(callback); - slot.emit(5); - expect(callback).toBeCalled(); - }); - - test('listen once', () => { - const slot = new Slot(); - const callback = vi.fn(v => expect(v).toBe(5)); - slot.once(callback); - slot.emit(5); - slot.emit(6); - expect(callback).toBeCalledTimes(1); - }); - - test('listen once with dispose', () => { - const slot = new Slot(); - const callback = vi.fn(() => { - throw new Error(''); - }); - const disposable = slot.once(callback); - disposable.dispose(); - slot.emit(); - expect(callback).toBeCalledTimes(0); - }); - - test('cycle emit', () => { - const slot = new Slot(); - const callback = vi.fn(v => slot.emit(v + 1)); - slot.on(callback); - slot.emit(0); - expect(callback).toBeCalledTimes(1); - expect(callback).toBeCalledWith(0); - }); -}); diff --git a/blocksuite/framework/global/src/slot/disposable.ts b/blocksuite/framework/global/src/disposable/index.ts similarity index 71% rename from blocksuite/framework/global/src/slot/disposable.ts rename to blocksuite/framework/global/src/disposable/index.ts index 73081c6a2d..5022223e4a 100644 --- a/blocksuite/framework/global/src/slot/disposable.ts +++ b/blocksuite/framework/global/src/disposable/index.ts @@ -1,15 +1,19 @@ +import { Subject, Subscription } from 'rxjs'; + type DisposeCallback = () => void; export interface Disposable { dispose: DisposeCallback; } -export interface DisposableManager extends Disposable { - add(d: Disposable | DisposeCallback): void; -} +export type DisposableMember = + | Disposable + | Subscription + | Subject + | DisposeCallback; -export class DisposableGroup implements DisposableManager { - private _disposables: Disposable[] = []; +export class DisposableGroup { + private _disposables: DisposableMember[] = []; private _disposed = false; @@ -21,14 +25,12 @@ export class DisposableGroup implements DisposableManager { * Add to group to be disposed with others. * This will be immediately disposed if this group has already been disposed. */ - add(d: Disposable | DisposeCallback) { - if (typeof d === 'function') { - if (this._disposed) d(); - else this._disposables.push({ dispose: d }); - } else { - if (this._disposed) d.dispose(); - else this._disposables.push(d); + add(d: DisposableMember) { + if (this._disposed) { + disposeMember(d); + return; } + this._disposables.push(d); } addFromEvent( @@ -83,18 +85,22 @@ export class DisposableGroup implements DisposableManager { } } -export function flattenDisposables(disposables: Disposable[]): Disposable { - return { - dispose: () => disposeAll(disposables), - }; -} - -function disposeAll(disposables: Disposable[]) { - for (const disposable of disposables) { - try { +export function disposeMember(disposable: DisposableMember) { + try { + if (disposable instanceof Subscription) { + disposable.unsubscribe(); + } else if (disposable instanceof Subject) { + disposable.complete(); + } else if (typeof disposable === 'function') { + disposable(); + } else { disposable.dispose(); - } catch (err) { - console.error(err); } + } catch (e) { + console.error(e); } } + +function disposeAll(disposables: DisposableMember[]) { + disposables.forEach(disposeMember); +} diff --git a/blocksuite/framework/global/src/lit/with-disposable.ts b/blocksuite/framework/global/src/lit/with-disposable.ts index 24d7cf0959..a938ec303c 100644 --- a/blocksuite/framework/global/src/lit/with-disposable.ts +++ b/blocksuite/framework/global/src/lit/with-disposable.ts @@ -1,6 +1,6 @@ import type { LitElement } from 'lit'; -import { DisposableGroup } from '../slot/disposable.js'; +import { DisposableGroup } from '../disposable/index.js'; import type { Constructor } from '../utils/types.js'; // See https://lit.dev/docs/composition/mixins/#mixins-in-typescript diff --git a/blocksuite/framework/global/src/slot/index.ts b/blocksuite/framework/global/src/slot/index.ts deleted file mode 100644 index 314daecf98..0000000000 --- a/blocksuite/framework/global/src/slot/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './disposable.js'; -export * from './slot.js'; diff --git a/blocksuite/framework/global/src/slot/slot.ts b/blocksuite/framework/global/src/slot/slot.ts deleted file mode 100644 index beac24d955..0000000000 --- a/blocksuite/framework/global/src/slot/slot.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { type Disposable, flattenDisposables } from './disposable.js'; - -export class Slot implements Disposable { - private _callbacks: ((v: T) => unknown)[] = []; - - private _disposables: Disposable[] = []; - - private _emitting = false; - - dispose() { - flattenDisposables(this._disposables).dispose(); - this._callbacks = []; - this._disposables = []; - } - - emit(v: T) { - // Prevent recursive emit calls - if (this._emitting) { - return; - } - - const prevEmitting = this._emitting; - this._emitting = true; - try { - this._callbacks.forEach(f => { - try { - f(v); - } catch (err) { - console.error(err); - } - }); - } finally { - this._emitting = prevEmitting; - } - } - - on(callback: (v: T) => unknown): Disposable { - if (this._emitting) { - const newCallback = [...this._callbacks, callback]; - this._callbacks = newCallback; - } else { - this._callbacks.push(callback); - } - return { - dispose: () => { - if (this._emitting) { - this._callbacks = this._callbacks.filter(v => v !== callback); - } else { - const index = this._callbacks.indexOf(callback); - if (index > -1) { - this._callbacks.splice(index, 1); // remove one item only - } - } - }, - }; - } - - once(callback: (v: T) => unknown): Disposable { - let dispose: Disposable['dispose'] | undefined = undefined; - const handler = (v: T) => { - callback(v); - if (dispose) { - dispose(); - } - }; - const disposable = this.on(handler); - dispose = disposable.dispose; - return disposable; - } - - filter(testFun: (v: T) => boolean): Slot { - const result = new Slot(); - // if the original slot is disposed, dispose the filtered one - this._disposables.push({ - dispose: () => result.dispose(), - }); - - this.on((v: T) => { - if (testFun(v)) { - result.emit(v); - } - }); - - return result; - } -} diff --git a/blocksuite/framework/inline/package.json b/blocksuite/framework/inline/package.json index 1ba5247695..efa1d774bc 100644 --- a/blocksuite/framework/inline/package.json +++ b/blocksuite/framework/inline/package.json @@ -28,6 +28,7 @@ "@blocksuite/global": "workspace:*", "@preact/signals-core": "^1.8.0", "lit": "^3.2.0", + "rxjs": "^7.8.1", "yjs": "^13.6.21", "zod": "^3.23.8" }, diff --git a/blocksuite/framework/inline/src/components/v-element.ts b/blocksuite/framework/inline/src/components/v-element.ts index 4d9d683682..8ae0c9ed49 100644 --- a/blocksuite/framework/inline/src/components/v-element.ts +++ b/blocksuite/framework/inline/src/components/v-element.ts @@ -1,6 +1,6 @@ +import { DisposableGroup } from '@blocksuite/global/disposable'; import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; import { SignalWatcher } from '@blocksuite/global/lit'; -import { DisposableGroup } from '@blocksuite/global/slot'; import { effect, signal } from '@preact/signals-core'; import { html, LitElement } from 'lit'; import { property } from 'lit/decorators.js'; diff --git a/blocksuite/framework/inline/src/inline-editor.ts b/blocksuite/framework/inline/src/inline-editor.ts index be26d89b57..71a3b51bc6 100644 --- a/blocksuite/framework/inline/src/inline-editor.ts +++ b/blocksuite/framework/inline/src/inline-editor.ts @@ -1,7 +1,8 @@ +import { DisposableGroup } from '@blocksuite/global/disposable'; import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; -import { DisposableGroup, Slot } from '@blocksuite/global/slot'; import { type Signal, signal } from '@preact/signals-core'; import { nothing, render, type TemplateResult } from 'lit'; +import { Subject } from 'rxjs'; import type * as Y from 'yjs'; import type { VLine } from './components/v-line.js'; @@ -160,19 +161,19 @@ export class InlineEditor< }; readonly slots = { - mounted: new Slot(), - unmounted: new Slot(), - renderComplete: new Slot(), - textChange: new Slot(), - inlineRangeSync: new Slot(), + mounted: new Subject(), + unmounted: new Subject(), + renderComplete: new Subject(), + textChange: new Subject(), + inlineRangeSync: new Subject(), /** * Corresponding to the `compositionUpdate` and `beforeInput` events, and triggered only when the `inlineRange` is not null. */ - inputting: new Slot(), + inputting: new Subject(), /** * Triggered only when the `inlineRange` is not null. */ - keydown: new Slot(), + keydown: new Subject(), }; readonly vLineRenderer: ((vLine: VLine) => TemplateResult) | null; @@ -252,7 +253,7 @@ export class InlineEditor< this.renderService.mount(); this._mounted = true; - this.slots.mounted.emit(); + this.slots.mounted.next(); this.render(); } @@ -267,7 +268,7 @@ export class InlineEditor< this._rootElement = null; this._mounted = false; this.disposables.dispose(); - this.slots.unmounted.emit(); + this.slots.unmounted.next(); } setReadonly(isReadonly: boolean): void { diff --git a/blocksuite/framework/inline/src/services/event.ts b/blocksuite/framework/inline/src/services/event.ts index f01ead34ff..6caf722956 100644 --- a/blocksuite/framework/inline/src/services/event.ts +++ b/blocksuite/framework/inline/src/services/event.ts @@ -118,7 +118,7 @@ export class EventService { this.editor as InlineEditor ); - this.editor.slots.inputting.emit(); + this.editor.slots.inputting.next(); }; private readonly _onClick = (event: MouseEvent) => { @@ -180,7 +180,7 @@ export class EventService { }); } - this.editor.slots.inputting.emit(); + this.editor.slots.inputting.next(); }; private readonly _onCompositionStart = () => { @@ -215,14 +215,14 @@ export class EventService { ) return; - this.editor.slots.inputting.emit(); + this.editor.slots.inputting.next(); }; private readonly _onKeyDown = (event: KeyboardEvent) => { const inlineRange = this.editor.getInlineRange(); if (!inlineRange) return; - this.editor.slots.keydown.emit(event); + this.editor.slots.keydown.next(event); if ( !event.shiftKey && diff --git a/blocksuite/framework/inline/src/services/range.ts b/blocksuite/framework/inline/src/services/range.ts index b8cdedd7cb..ec9b896bad 100644 --- a/blocksuite/framework/inline/src/services/range.ts +++ b/blocksuite/framework/inline/src/services/range.ts @@ -257,7 +257,8 @@ export class RangeService { if (editor.inlineRangeProviderOverride) return; if (this.editor.renderService.rendering) { - editor.slots.renderComplete.once(() => { + const subscription = editor.slots.renderComplete.subscribe(() => { + subscription.unsubscribe(); this.syncInlineRange(newInlineRange); }); } else { @@ -308,11 +309,14 @@ export class RangeService { selection.addRange(newRange); this.editor.rootElement.focus(); - this.editor.slots.inlineRangeSync.emit(newRange); + this.editor.slots.inlineRangeSync.next(newRange); } else { - this.editor.slots.renderComplete.once(() => { - this.syncInlineRange(inlineRange); - }); + const subscription = this.editor.slots.renderComplete.subscribe( + () => { + subscription.unsubscribe(); + this.syncInlineRange(inlineRange); + } + ); } } catch (error) { console.error('failed to apply inline range'); @@ -322,7 +326,10 @@ export class RangeService { }; if (this.editor.renderService.rendering) { - this.editor.slots.renderComplete.once(handler); + const subscription = this.editor.slots.renderComplete.subscribe(() => { + subscription.unsubscribe(); + handler(); + }); } else { handler(); } diff --git a/blocksuite/framework/inline/src/services/render.ts b/blocksuite/framework/inline/src/services/render.ts index 8050a3499e..dca607b4f4 100644 --- a/blocksuite/framework/inline/src/services/render.ts +++ b/blocksuite/framework/inline/src/services/render.ts @@ -14,7 +14,7 @@ export class RenderService { _: Y.YTextEvent, transaction: Y.Transaction ) => { - this.editor.slots.textChange.emit(); + this.editor.slots.textChange.next(); const yText = this.editor.yText; @@ -153,7 +153,7 @@ export class RenderService { .waitForUpdate() .then(() => { this._rendering = false; - this.editor.slots.renderComplete.emit(); + this.editor.slots.renderComplete.next(); this.editor.syncInlineRange(); }) .catch(console.error); diff --git a/blocksuite/framework/store/package.json b/blocksuite/framework/store/package.json index cf50d64d0d..d97b06b725 100644 --- a/blocksuite/framework/store/package.json +++ b/blocksuite/framework/store/package.json @@ -26,6 +26,7 @@ "lodash.merge": "^4.6.2", "minimatch": "^10.0.1", "nanoid": "^5.0.7", + "rxjs": "^7.8.1", "y-protocols": "^1.0.6", "yjs": "^13.6.21", "zod": "^3.23.8" diff --git a/blocksuite/framework/store/src/__tests__/collection.unit.spec.ts b/blocksuite/framework/store/src/__tests__/collection.unit.spec.ts index b386e111b6..2295849e3a 100644 --- a/blocksuite/framework/store/src/__tests__/collection.unit.spec.ts +++ b/blocksuite/framework/store/src/__tests__/collection.unit.spec.ts @@ -1,4 +1,4 @@ -import type { Slot } from '@blocksuite/global/slot'; +import type { Subject } from 'rxjs'; import { assert, beforeEach, describe, expect, it, vi } from 'vitest'; import { applyUpdate, type Doc, encodeStateAsUpdate } from 'yjs'; @@ -36,8 +36,13 @@ function serializCollection(doc: Doc): Record { }; } -function waitOnce(slot: Slot) { - return new Promise(resolve => slot.once(val => resolve(val))); +function waitOnce(slot: Subject) { + return new Promise(resolve => { + const subscription = slot.subscribe(val => { + subscription.unsubscribe(); + resolve(val); + }); + }); } function createRoot(doc: Store) { @@ -150,8 +155,8 @@ describe('basic', () => { const readyCallback = vi.fn(); const rootAddedCallback = vi.fn(); - doc.slots.ready.on(readyCallback); - doc.slots.rootAdded.on(rootAddedCallback); + doc.slots.ready.subscribe(readyCallback); + doc.slots.rootAdded.subscribe(rootAddedCallback); doc.load(() => { const rootId = doc.addBlock('affine:page', { @@ -428,7 +433,7 @@ describe('addBlock', () => { ); let called = false; - collection.slots.docListUpdated.on(() => { + collection.slots.docListUpdated.subscribe(() => { called = true; }); diff --git a/blocksuite/framework/store/src/__tests__/doc.unit.spec.ts b/blocksuite/framework/store/src/__tests__/doc.unit.spec.ts index cda8c78d95..e93c1f0d71 100644 --- a/blocksuite/framework/store/src/__tests__/doc.unit.spec.ts +++ b/blocksuite/framework/store/src/__tests__/doc.unit.spec.ts @@ -41,7 +41,7 @@ test('trigger props updated', () => { expect(rootModel).not.toBeNull(); const onPropsUpdated = vi.fn(); - rootModel.propsUpdated.on(onPropsUpdated); + rootModel.propsUpdated.subscribe(onPropsUpdated); const getColor = () => (rootModel.yBlock.get('prop:style') as Y.Map).get('color'); @@ -101,7 +101,7 @@ test('stash and pop', () => { expect(rootModel).not.toBeNull(); const onPropsUpdated = vi.fn(); - rootModel.propsUpdated.on(onPropsUpdated); + rootModel.propsUpdated.subscribe(onPropsUpdated); const getCount = () => rootModel.yBlock.get('prop:count'); const getColor = () => @@ -171,7 +171,7 @@ test('always get latest value in onChange', () => { expect(rootModel).not.toBeNull(); let value: unknown; - rootModel.propsUpdated.on(({ key }) => { + rootModel.propsUpdated.subscribe(({ key }) => { // @ts-expect-error ignore value = rootModel[key]; }); diff --git a/blocksuite/framework/store/src/__tests__/yjs.unit.spec.ts b/blocksuite/framework/store/src/__tests__/yjs.unit.spec.ts index 095950db4f..ce66c8ce6a 100644 --- a/blocksuite/framework/store/src/__tests__/yjs.unit.spec.ts +++ b/blocksuite/framework/store/src/__tests__/yjs.unit.spec.ts @@ -1,4 +1,4 @@ -import { Slot } from '@blocksuite/global/slot'; +import { Subject } from 'rxjs'; import { describe, expect, test } from 'vitest'; import * as Y from 'yjs'; @@ -184,7 +184,7 @@ test('flat', () => { map.set('prop:col.c.d', 3); map.set('prop:col.c.e', 4); - const reactive = new ReactiveFlatYMap(map, new Slot()); + const reactive = new ReactiveFlatYMap(map, new Subject()); const proxy = reactive.proxy as Record; proxy.col.c.d = 200; expect(map.get('prop:col.c.d')).toBe(200); diff --git a/blocksuite/framework/store/src/extension/selection/selection-extension.ts b/blocksuite/framework/store/src/extension/selection/selection-extension.ts index 8f584e0f56..b6f795fa94 100644 --- a/blocksuite/framework/store/src/extension/selection/selection-extension.ts +++ b/blocksuite/framework/store/src/extension/selection/selection-extension.ts @@ -1,6 +1,6 @@ import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; -import { Slot } from '@blocksuite/global/slot'; import { computed, signal } from '@preact/signals-core'; +import { Subject } from 'rxjs'; import { nanoid } from '../../utils/id-generator'; import type { StackItem } from '../../yjs'; @@ -42,8 +42,8 @@ export class StoreSelectionExtension extends StoreExtension { }; slots = { - changed: new Slot(), - remoteChanged: new Slot>(), + changed: new Subject(), + remoteChanged: new Subject>(), }; override loaded() { @@ -98,7 +98,7 @@ export class StoreSelectionExtension extends StoreExtension { map.set(id, selections); }); this._remoteSelections.value = map; - this.slots.remoteChanged.emit(map); + this.slots.remoteChanged.next(map); } } ); @@ -162,7 +162,7 @@ export class StoreSelectionExtension extends StoreExtension { this._id, selections.map(s => s.toJSON()) ); - this.slots.changed.emit(selections); + this.slots.changed.next(selections); } setGroup(group: string, selections: BaseSelection[]) { diff --git a/blocksuite/framework/store/src/model/block/block-model.ts b/blocksuite/framework/store/src/model/block/block-model.ts index af7ef59a5b..411a8e142a 100644 --- a/blocksuite/framework/store/src/model/block/block-model.ts +++ b/blocksuite/framework/store/src/model/block/block-model.ts @@ -1,5 +1,7 @@ -import { type Disposable, Slot } from '@blocksuite/global/slot'; +import type { Disposable } from '@blocksuite/global/disposable'; import { computed, type Signal, signal } from '@preact/signals-core'; +import { Subject } from 'rxjs'; +import { take } from 'rxjs/operators'; import type { Text } from '../../reactive/index.js'; import type { Store } from '../store/store.js'; @@ -57,9 +59,9 @@ export class BlockModel< }, new Map()) ); - created = new Slot(); + created = new Subject(); - deleted = new Slot(); + deleted = new Subject(); id!: string; @@ -76,7 +78,7 @@ export class BlockModel< pop!: (prop: keyof Props & string) => void; - propsUpdated = new Slot<{ key: string }>(); + propsUpdated = new Subject<{ key: string }>(); stash!: (prop: keyof Props & string) => void; @@ -124,26 +126,30 @@ export class BlockModel< constructor() { super(); - this._onCreated = this.created.once(() => { - this._children.value = this.yBlock.get('sys:children').toArray(); - this.yBlock.get('sys:children').observe(event => { - this._children.value = event.target.toArray(); - }); - this.yBlock.observe(event => { - if (event.keysChanged.has('sys:children')) { - this._children.value = this.yBlock.get('sys:children').toArray(); - } - }); - }); - this._onDeleted = this.deleted.once(() => { - this._onCreated.dispose(); - }); + this._onCreated = { + dispose: this.created.pipe(take(1)).subscribe(() => { + this._children.value = this.yBlock.get('sys:children').toArray(); + this.yBlock.get('sys:children').observe(event => { + this._children.value = event.target.toArray(); + }); + this.yBlock.observe(event => { + if (event.keysChanged.has('sys:children')) { + this._children.value = this.yBlock.get('sys:children').toArray(); + } + }); + }).unsubscribe, + }; + this._onDeleted = { + dispose: this.deleted.pipe(take(1)).subscribe(() => { + this._onCreated.dispose(); + }).unsubscribe, + }; } dispose() { - this.created.dispose(); - this.deleted.dispose(); - this.propsUpdated.dispose(); + this.created.complete(); + this.deleted.complete(); + this.propsUpdated.complete(); } firstChild(): BlockModel | null { diff --git a/blocksuite/framework/store/src/model/block/sync-controller.ts b/blocksuite/framework/store/src/model/block/sync-controller.ts index 55346347f1..5d9edb0698 100644 --- a/blocksuite/framework/store/src/model/block/sync-controller.ts +++ b/blocksuite/framework/store/src/model/block/sync-controller.ts @@ -142,7 +142,10 @@ export class SyncController { this.model[key] = value; }); }); - model.deleted.once(dispose); + const subscription = model.deleted.subscribe(() => { + subscription.unsubscribe(); + dispose(); + }); return { ...acc, [`${key}$`]: data, diff --git a/blocksuite/framework/store/src/model/doc.ts b/blocksuite/framework/store/src/model/doc.ts index 5be2a5a9a2..ee0be5ea92 100644 --- a/blocksuite/framework/store/src/model/doc.ts +++ b/blocksuite/framework/store/src/model/doc.ts @@ -1,4 +1,4 @@ -import type { Slot } from '@blocksuite/global/slot'; +import type { Subject } from 'rxjs'; import type * as Y from 'yjs'; import type { AwarenessStore } from '../yjs/awareness.js'; @@ -24,8 +24,8 @@ export interface Doc { dispose(): void; slots: { - historyUpdated: Slot; - yBlockUpdated: Slot< + historyUpdated: Subject; + yBlockUpdated: Subject< | { type: 'add'; id: string; diff --git a/blocksuite/framework/store/src/model/store/store.ts b/blocksuite/framework/store/src/model/store/store.ts index 5820a60981..103d55f31a 100644 --- a/blocksuite/framework/store/src/model/store/store.ts +++ b/blocksuite/framework/store/src/model/store/store.ts @@ -1,7 +1,8 @@ import { Container, type ServiceProvider } from '@blocksuite/global/di'; +import { DisposableGroup } from '@blocksuite/global/disposable'; import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; -import { DisposableGroup, Slot } from '@blocksuite/global/slot'; import { computed, signal } from '@preact/signals-core'; +import { Subject } from 'rxjs'; import type { ExtensionType } from '../../extension/extension.js'; import { @@ -67,15 +68,15 @@ export class Store { readonly slots: Doc['slots'] & { /** This is always triggered after `doc.load` is called. */ - ready: Slot; + ready: Subject; /** * This fires when the root block is added via API call or has just been initialized from existing ydoc. * useful for internal block UI components to start subscribing following up events. * Note that at this moment, the whole block tree may not be fully initialized yet. */ - rootAdded: Slot; - rootDeleted: Slot; - blockUpdated: Slot< + rootAdded: Subject; + rootDeleted: Subject; + blockUpdated: Subject< | { type: 'add'; id: string; @@ -313,13 +314,15 @@ export class Store { return this._doc.withoutTransact.bind(this._doc); } + private _isDisposed = false; + constructor({ doc, readonly, query, provider, extensions }: StoreOptions) { this._doc = doc; this.slots = { - ready: new Slot(), - rootAdded: new Slot(), - rootDeleted: new Slot(), - blockUpdated: new Slot(), + ready: new Subject(), + rootAdded: new Subject(), + rootDeleted: new Subject(), + blockUpdated: new Subject(), historyUpdated: this._doc.slots.historyUpdated, yBlockUpdated: this._doc.slots.yBlockUpdated, }; @@ -362,18 +365,31 @@ export class Store { private readonly _subscribeToSlots = () => { this.disposableGroup.add( - this._doc.slots.yBlockUpdated.on(({ type, id }) => { - switch (type) { - case 'add': { - this._onBlockAdded(id); - return; - } - case 'delete': { - this._onBlockRemoved(id); - return; + this._doc.slots.yBlockUpdated.subscribe( + ({ type, id }: { type: string; id: string }) => { + switch (type) { + case 'add': { + this._onBlockAdded(id); + return; + } + case 'delete': { + this._onBlockRemoved(id); + return; + } + case 'update': { + const block = this.getBlock(id); + if (!block) return; + this.slots.blockUpdated.next({ + type: 'update', + id, + flavour: block.flavour, + props: { key: 'content' }, + }); + return; + } } } - }) + ) ); this.disposableGroup.add(this.slots.ready); this.disposableGroup.add(this.slots.blockUpdated); @@ -412,10 +428,10 @@ export class Store { const options: BlockOptions = { onChange: (block, key) => { if (key) { - block.model.propsUpdated.emit({ key }); + block.model.propsUpdated.next({ key }); } - this.slots.blockUpdated.emit({ + this.slots.blockUpdated.next({ type: 'update', id, flavour: block.flavour, @@ -431,13 +447,13 @@ export class Store { ...this._blocks.value, [id]: block, }; - block.model.created.emit(); + block.model.created.next(); if (block.model.role === 'root') { - this.slots.rootAdded.emit(id); + this.slots.rootAdded.next(id); } - this.slots.blockUpdated.emit({ + this.slots.blockUpdated.next({ type: 'add', id, init, @@ -456,13 +472,13 @@ export class Store { if (!block) return; if (block.model.role === 'root') { - this.slots.rootDeleted.emit(id); + this.slots.rootDeleted.next(id); } - this.slots.blockUpdated.emit({ + this.slots.blockUpdated.next({ type: 'delete', id, - flavour: block.model.flavour, + flavour: block.flavour, parent: this.getParent(block.model)?.id ?? '', model: block.model, }); @@ -470,7 +486,7 @@ export class Store { const { [id]: _, ...blocks } = this._blocks.peek(); this._blocks.value = blocks; - block.model.deleted.emit(); + block.model.deleted.next(); block.model.dispose(); } catch (e) { console.error('An error occurred while removing block:'); @@ -604,8 +620,12 @@ export class Store { this._provider.getAll(StoreExtensionIdentifier).forEach(ext => { ext.disposed(); }); - + this.slots.ready.complete(); + this.slots.rootAdded.complete(); + this.slots.rootDeleted.complete(); + this.slots.blockUpdated.complete(); this.disposableGroup.dispose(); + this._isDisposed = true; } getBlock(id: string): Block | undefined { @@ -705,16 +725,18 @@ export class Store { } load(initFn?: () => void) { - if (this.disposableGroup.disposed) { + if (this._isDisposed) { this.disposableGroup = new DisposableGroup(); this._subscribeToSlots(); + this._isDisposed = false; } this._doc.load(initFn); this._provider.getAll(StoreExtensionIdentifier).forEach(ext => { ext.loaded(); }); - this.slots.ready.emit(); + this.slots.ready.next(); + this.slots.rootAdded.next(this.root?.id ?? ''); return this; } diff --git a/blocksuite/framework/store/src/model/workspace-meta.ts b/blocksuite/framework/store/src/model/workspace-meta.ts index d8096a5613..4f55148661 100644 --- a/blocksuite/framework/store/src/model/workspace-meta.ts +++ b/blocksuite/framework/store/src/model/workspace-meta.ts @@ -1,4 +1,4 @@ -import type { Slot } from '@blocksuite/global/slot'; +import type { Subject } from 'rxjs'; export type Tag = { id: string; @@ -39,8 +39,8 @@ export interface WorkspaceMeta { get docs(): unknown[] | undefined; initialize(): void; - commonFieldsUpdated: Slot; - docMetaAdded: Slot; - docMetaRemoved: Slot; - docMetaUpdated: Slot; + commonFieldsUpdated: Subject; + docMetaAdded: Subject; + docMetaRemoved: Subject; + docMetaUpdated: Subject; } diff --git a/blocksuite/framework/store/src/model/workspace.ts b/blocksuite/framework/store/src/model/workspace.ts index 8f2dcd0d0f..139a6d56d6 100644 --- a/blocksuite/framework/store/src/model/workspace.ts +++ b/blocksuite/framework/store/src/model/workspace.ts @@ -1,5 +1,5 @@ -import type { Slot } from '@blocksuite/global/slot'; import type { BlobEngine } from '@blocksuite/sync'; +import type { Subject } from 'rxjs'; import type { Awareness } from 'y-protocols/awareness.js'; import type * as Y from 'yjs'; @@ -20,9 +20,9 @@ export interface Workspace { get docs(): Map; slots: { - docListUpdated: Slot; - docCreated: Slot; - docRemoved: Slot; + docListUpdated: Subject; + docCreated: Subject; + docRemoved: Subject; }; createDoc(options?: CreateBlocksOptions): Store; diff --git a/blocksuite/framework/store/src/reactive/flat-native-y.ts b/blocksuite/framework/store/src/reactive/flat-native-y.ts index bccf776d80..1a74a160e4 100644 --- a/blocksuite/framework/store/src/reactive/flat-native-y.ts +++ b/blocksuite/framework/store/src/reactive/flat-native-y.ts @@ -1,6 +1,6 @@ import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; -import type { Slot } from '@blocksuite/global/slot'; import { signal } from '@preact/signals-core'; +import type { Subject } from 'rxjs'; import { Array as YArray, Map as YMap, @@ -29,7 +29,7 @@ type CreateProxyOptions = { basePath?: string; onChange?: OnChange; transform: Transform; - onDispose: Slot; + onDispose: Subject; shouldByPassSignal: () => boolean; shouldByPassYjs: () => boolean; byPassSignalUpdate: (fn: () => void) => void; @@ -113,17 +113,19 @@ function createProxy( } const signalData = signal(value); root[signalKey] = signalData; - onDispose.once( - signalData.subscribe(next => { - if (!initialized()) { - return; - } - byPassSignalUpdate(() => { - proxy[p] = next; - onChange?.(firstKey); - }); - }) - ); + const unsubscribe = signalData.subscribe(next => { + if (!initialized()) { + return; + } + byPassSignalUpdate(() => { + proxy[p] = next; + onChange?.(firstKey); + }); + }); + const subscription = onDispose.subscribe(() => { + subscription.unsubscribe(); + unsubscribe(); + }); return; } byPassSignalUpdate(() => { @@ -464,7 +466,7 @@ export class ReactiveFlatYMap extends BaseReactiveYData< constructor( protected readonly _ySource: YMap, - private readonly _onDispose: Slot, + private readonly _onDispose: Subject, private readonly _onChange?: OnChange ) { super(); @@ -477,17 +479,19 @@ export class ReactiveFlatYMap extends BaseReactiveYData< Object.entries(source).forEach(([key, value]) => { const signalData = signal(value); source[`${key}$`] = signalData; - _onDispose.once( - signalData.subscribe(next => { - if (!this._initialized) { - return; - } - this._updateWithSkip(() => { - proxy[key] = next; - this._onChange?.(key); - }); - }) - ); + const unsubscribe = signalData.subscribe(next => { + if (!this._initialized) { + return; + } + this._updateWithSkip(() => { + proxy[key] = next; + this._onChange?.(key); + }); + }); + const subscription = _onDispose.subscribe(() => { + subscription.unsubscribe(); + unsubscribe(); + }); }); this._proxy = proxy; diff --git a/blocksuite/framework/store/src/test/test-doc.ts b/blocksuite/framework/store/src/test/test-doc.ts index 5290236b5d..b5debc647d 100644 --- a/blocksuite/framework/store/src/test/test-doc.ts +++ b/blocksuite/framework/store/src/test/test-doc.ts @@ -1,5 +1,5 @@ -import { Slot } from '@blocksuite/global/slot'; import { signal } from '@preact/signals-core'; +import { Subject } from 'rxjs'; import * as Y from 'yjs'; import type { YBlock } from '../model/block/types.js'; @@ -34,7 +34,7 @@ export class TestDoc implements Doc { private readonly _historyObserver = () => { this._updateCanUndoRedoSignals(); - this.slots.historyUpdated.emit(); + this.slots.historyUpdated.next(); }; private readonly _initSubDoc = () => { @@ -45,7 +45,7 @@ export class TestDoc implements Doc { }); this.rootDoc.getMap('spaces').set(this.id, subDoc); this._loaded = true; - this._onLoadSlot.emit(); + this._onLoadSlot.next(); } else { this._loaded = false; this.rootDoc.on('subdocs', this._onSubdocEvent); @@ -56,7 +56,7 @@ export class TestDoc implements Doc { private _loaded!: boolean; - private readonly _onLoadSlot = new Slot(); + private readonly _onLoadSlot = new Subject(); private readonly _onSubdocEvent = ({ loaded, @@ -71,7 +71,7 @@ export class TestDoc implements Doc { } this.rootDoc.off('subdocs', this._onSubdocEvent); this._loaded = true; - this._onLoadSlot.emit(); + this._onLoadSlot.next(); }; /** Indicate whether the block tree is ready */ @@ -105,8 +105,8 @@ export class TestDoc implements Doc { readonly rootDoc: Y.Doc; readonly slots = { - historyUpdated: new Slot(), - yBlockUpdated: new Slot< + historyUpdated: new Subject(), + yBlockUpdated: new Subject< | { type: 'add'; id: string; @@ -186,11 +186,11 @@ export class TestDoc 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>) { @@ -244,12 +244,12 @@ export class TestDoc implements Doc { private _destroy() { this._ySpaceDoc.destroy(); - this._onLoadSlot.dispose(); + this._onLoadSlot.complete(); this._loaded = false; } dispose() { - this.slots.historyUpdated.dispose(); + this.slots.historyUpdated.complete(); if (this.ready) { this._yBlocks.unobserveDeep(this._handleYEvents); diff --git a/blocksuite/framework/store/src/test/test-meta.ts b/blocksuite/framework/store/src/test/test-meta.ts index aad37debcb..4aef9ee097 100644 --- a/blocksuite/framework/store/src/test/test-meta.ts +++ b/blocksuite/framework/store/src/test/test-meta.ts @@ -1,4 +1,4 @@ -import { Slot } from '@blocksuite/global/slot'; +import { Subject } from 'rxjs'; import type * as Y from 'yjs'; import type { @@ -45,15 +45,15 @@ export class TestMeta implements WorkspaceMeta { DocCollectionMetaState[keyof DocCollectionMetaState] >; - commonFieldsUpdated = new Slot(); + commonFieldsUpdated = new Subject(); readonly doc: Y.Doc; - docMetaAdded = new Slot(); + docMetaAdded = new Subject(); - docMetaRemoved = new Slot(); + docMetaRemoved = new Subject(); - docMetaUpdated = new Slot(); + docMetaUpdated = new Subject(); readonly id: string = 'meta'; @@ -103,7 +103,7 @@ export class TestMeta implements WorkspaceMeta { } private _handleCommonFieldsEvent() { - this.commonFieldsUpdated.emit(); + this.commonFieldsUpdated.next(); } private _handleDocMetaEvent() { @@ -113,7 +113,7 @@ export class TestMeta implements WorkspaceMeta { docMetas.forEach(docMeta => { if (!_prevDocs.has(docMeta.id)) { - this.docMetaAdded.emit(docMeta.id); + this.docMetaAdded.next(docMeta.id); } newDocs.add(docMeta.id); }); @@ -121,13 +121,13 @@ export class TestMeta 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) { @@ -204,6 +204,6 @@ export class TestMeta implements WorkspaceMeta { setProperties(meta: DocsPropertiesMeta) { this._proxy.properties = meta; - this.docMetaUpdated.emit(); + this.docMetaUpdated.next(); } } diff --git a/blocksuite/framework/store/src/test/test-workspace.ts b/blocksuite/framework/store/src/test/test-workspace.ts index 2948e3933f..82b25c7923 100644 --- a/blocksuite/framework/store/src/test/test-workspace.ts +++ b/blocksuite/framework/store/src/test/test-workspace.ts @@ -1,5 +1,4 @@ import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; -import { Slot } from '@blocksuite/global/slot'; import { NoopLogger } from '@blocksuite/global/utils'; import { AwarenessEngine, @@ -11,6 +10,7 @@ import { MemoryBlobSource, NoopDocSource, } from '@blocksuite/sync'; +import { Subject } from 'rxjs'; import { Awareness } from 'y-protocols/awareness.js'; import * as Y from 'yjs'; @@ -67,9 +67,9 @@ export class TestWorkspace implements Workspace { meta: WorkspaceMeta; slots = { - docListUpdated: new Slot(), - docRemoved: new Slot(), - docCreated: new Slot(), + docListUpdated: new Subject(), + docRemoved: new Subject(), + docCreated: new Subject(), }; get docs() { @@ -116,7 +116,7 @@ export class TestWorkspace implements Workspace { } private _bindDocMetaEvents() { - this.meta.docMetaAdded.on(docId => { + this.meta.docMetaAdded.subscribe(docId => { const doc = new TestDoc({ id: docId, collection: this, @@ -126,14 +126,14 @@ export class TestWorkspace 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 space = this.getBlockCollection(id); if (!space) return; this.blockCollections.delete(id); space.remove(); - this.slots.docRemoved.emit(id); + this.slots.docRemoved.next(id); }); } @@ -174,7 +174,7 @@ export class TestWorkspace implements Workspace { createDate: Date.now(), tags: [], }); - this.slots.docCreated.emit(docId); + this.slots.docCreated.next(docId); return this.getDoc(docId, { id: docId, query, diff --git a/blocksuite/framework/store/src/transformer/middleware.ts b/blocksuite/framework/store/src/transformer/middleware.ts index b37eae5bce..7a288ec687 100644 --- a/blocksuite/framework/store/src/transformer/middleware.ts +++ b/blocksuite/framework/store/src/transformer/middleware.ts @@ -1,4 +1,4 @@ -import type { Slot } from '@blocksuite/global/slot'; +import type { Subject } from 'rxjs'; import type { BlockModel, DraftModel, Store } from '../model/index.js'; import type { AssetsManager } from './assets.js'; @@ -95,10 +95,10 @@ export type AfterImportPayload = }; export type TransformerSlots = { - beforeImport: Slot; - afterImport: Slot; - beforeExport: Slot; - afterExport: Slot; + beforeImport: Subject; + afterImport: Subject; + beforeExport: Subject; + afterExport: Subject; }; type TransformerMiddlewareOptions = { diff --git a/blocksuite/framework/store/src/transformer/transformer.ts b/blocksuite/framework/store/src/transformer/transformer.ts index 7f0e3b2305..3f360eab79 100644 --- a/blocksuite/framework/store/src/transformer/transformer.ts +++ b/blocksuite/framework/store/src/transformer/transformer.ts @@ -1,6 +1,6 @@ import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; -import { Slot } from '@blocksuite/global/slot'; import { nextTick } from '@blocksuite/global/utils'; +import { Subject } from 'rxjs'; import { BlockModel, @@ -68,10 +68,10 @@ export class Transformer { private readonly _docCRUD: DocCRUD; private readonly _slots: TransformerSlots = { - beforeImport: new Slot(), - afterImport: new Slot(), - beforeExport: new Slot(), - afterExport: new Slot(), + beforeImport: new Subject(), + afterImport: new Subject(), + beforeExport: new Subject(), + afterExport: new Subject(), }; blockToSnapshot = ( @@ -99,7 +99,7 @@ export class Transformer { docToSnapshot = (doc: Store): DocSnapshot | undefined => { try { - this._slots.beforeExport.emit({ + this._slots.beforeExport.next({ type: 'page', page: doc, }); @@ -120,7 +120,7 @@ export class Transformer { meta, blocks, }; - this._slots.afterExport.emit({ + this._slots.afterExport.next({ type: 'page', page: doc, snapshot: docSnapshot, @@ -137,7 +137,7 @@ export class Transformer { sliceToSnapshot = (slice: Slice): SliceSnapshot | undefined => { try { - this._slots.beforeExport.emit({ + this._slots.beforeExport.next({ type: 'slice', slice, }); @@ -156,7 +156,7 @@ export class Transformer { pageId, content: contentSnapshot, }; - this._slots.afterExport.emit({ + this._slots.afterExport.next({ type: 'slice', slice, snapshot, @@ -191,7 +191,7 @@ export class Transformer { snapshotToDoc = async (snapshot: DocSnapshot): Promise => { try { - this._slots.beforeImport.emit({ + this._slots.beforeImport.next({ type: 'page', snapshot, }); @@ -200,7 +200,7 @@ export class Transformer { const doc = this.docCRUD.create(meta.id); doc.load(); await this.snapshotToBlock(blocks, doc); - this._slots.afterImport.emit({ + this._slots.afterImport.next({ type: 'page', snapshot, page: doc, @@ -247,7 +247,7 @@ export class Transformer { ): Promise => { SliceSnapshotSchema.parse(snapshot); try { - this._slots.beforeImport.emit({ + this._slots.beforeImport.next({ type: 'slice', snapshot, }); @@ -303,7 +303,7 @@ export class Transformer { pageId, }); - this._slots.afterImport.emit({ + this._slots.afterImport.next({ type: 'slice', snapshot, slice, @@ -376,7 +376,7 @@ export class Transformer { } private _blockToSnapshot(model: DraftModel): BlockSnapshot | null { - this._slots.beforeExport.emit({ + this._slots.beforeExport.next({ type: 'block', model, }); @@ -397,7 +397,7 @@ export class Transformer { ...snapshotLeaf, children, }; - this._slots.afterExport.emit({ + this._slots.afterExport.next({ type: 'block', model, snapshot, @@ -539,7 +539,7 @@ export class Transformer { ); } - this._slots.afterImport.emit({ + this._slots.afterImport.next({ type: 'block', model, snapshot: node.snapshot, @@ -627,7 +627,7 @@ export class Transformer { parent?: string, index?: number ) => { - this._slots.beforeImport.emit({ + this._slots.beforeImport.next({ type: 'block', snapshot: node, parent: parent, diff --git a/blocksuite/framework/sync/package.json b/blocksuite/framework/sync/package.json index 7915e81f7a..eeb4a18981 100644 --- a/blocksuite/framework/sync/package.json +++ b/blocksuite/framework/sync/package.json @@ -17,6 +17,7 @@ "idb": "^8.0.0", "idb-keyval": "^6.2.1", "lodash-es": "^4.17.21", + "rxjs": "^7.8.1", "y-protocols": "^1.0.6" }, "devDependencies": { diff --git a/blocksuite/framework/sync/src/doc/engine.ts b/blocksuite/framework/sync/src/doc/engine.ts index c94e0fc764..83fd4ff733 100644 --- a/blocksuite/framework/sync/src/doc/engine.ts +++ b/blocksuite/framework/sync/src/doc/engine.ts @@ -1,5 +1,5 @@ -import { Slot } from '@blocksuite/global/slot'; import type { Logger } from '@blocksuite/global/utils'; +import { Subject } from 'rxjs'; import type { Doc } from 'yjs'; import { SharedPriorityTarget } from '../utils/async-queue.js'; @@ -49,7 +49,7 @@ export class DocEngine { private _status: DocEngineStatus; - readonly onStatusChange = new Slot(); + readonly onStatusChange = new Subject(); readonly priorityTarget = new SharedPriorityTarget(); @@ -79,7 +79,7 @@ export class DocEngine { private setStatus(s: DocEngineStatus) { this.logger.debug(`syne-engine:${this.rootDocId} status change`, s); this._status = s; - this.onStatusChange.emit(s); + this.onStatusChange.next(s); } canGracefulStop() { @@ -133,10 +133,10 @@ export class DocEngine { ); cleanUp.push( - state.mainPeer.onStatusChange.on(() => { + state.mainPeer.onStatusChange.subscribe(() => { if (!signal.aborted) this.updateSyncingState(state.mainPeer, state.shadowPeers); - }).dispose + }).unsubscribe ); this.updateSyncingState(state.mainPeer, state.shadowPeers); @@ -153,10 +153,10 @@ export class DocEngine { this.logger ); cleanUp.push( - peer.onStatusChange.on(() => { + peer.onStatusChange.subscribe(() => { if (!signal.aborted) this.updateSyncingState(state.mainPeer, state.shadowPeers); - }).dispose + }).unsubscribe ); return peer; }); @@ -221,7 +221,7 @@ export class DocEngine { }); }), new Promise(resolve => { - this.onStatusChange.on(() => { + this.onStatusChange.subscribe(() => { if (this.canGracefulStop()) { resolve(); } @@ -243,7 +243,7 @@ export class DocEngine { } else { return Promise.race([ new Promise(resolve => { - this.onStatusChange.on(status => { + this.onStatusChange.subscribe(status => { if (isLoadedRootDoc(status)) { resolve(); } @@ -267,7 +267,7 @@ export class DocEngine { } else { return Promise.race([ new Promise(resolve => { - this.onStatusChange.on(status => { + this.onStatusChange.subscribe(status => { if (status.step === DocEngineStep.Synced) { resolve(); } diff --git a/blocksuite/framework/sync/src/doc/peer.ts b/blocksuite/framework/sync/src/doc/peer.ts index e7b5d1b95d..a8712bcbb4 100644 --- a/blocksuite/framework/sync/src/doc/peer.ts +++ b/blocksuite/framework/sync/src/doc/peer.ts @@ -1,6 +1,6 @@ -import { Slot } from '@blocksuite/global/slot'; import type { Logger } from '@blocksuite/global/utils'; import isEqual from 'lodash-es/isEqual'; +import { Subject } from 'rxjs'; import type { Doc } from 'yjs'; import { applyUpdate, @@ -110,7 +110,7 @@ export class SyncPeer { this.updateSyncStatus(); }; - readonly onStatusChange = new Slot(); + readonly onStatusChange = new Subject(); readonly state: { connectedDocs: Map; @@ -142,7 +142,7 @@ export class SyncPeer { if (!isEqual(s, this._status)) { this.logger.debug(`doc-peer:${this.name} status change`, s); this._status = s; - this.onStatusChange.emit(s); + this.onStatusChange.next(s); } } @@ -402,50 +402,50 @@ export class SyncPeer { } async waitForLoaded(abort?: AbortSignal) { - if (this.status.step > DocPeerStep.Loaded) { + if (this.status.step >= DocPeerStep.LoadingSubDoc) { return; - } else { - return Promise.race([ - new Promise(resolve => { - this.onStatusChange.on(status => { - if (status.step > DocPeerStep.Loaded) { - resolve(); - } - }); - }), - new Promise((_, reject) => { - if (abort?.aborted) { - reject(abort?.reason); - } - abort?.addEventListener('abort', () => { - reject(abort.reason); - }); - }), - ]); } + await Promise.race([ + new Promise(resolve => { + this.onStatusChange.subscribe(status => { + if (status.step >= DocPeerStep.LoadingSubDoc) { + resolve(); + } + }); + }), + new Promise((_, reject) => { + if (abort?.aborted) { + reject(abort.reason); + } + abort?.addEventListener('abort', () => { + reject(abort.reason); + }); + }), + ]); + throwIfAborted(abort); } async waitForSynced(abort?: AbortSignal) { - if (this.status.step >= DocPeerStep.Synced) { + if (this.status.step === DocPeerStep.Synced) { return; - } else { - return Promise.race([ - new Promise(resolve => { - this.onStatusChange.on(status => { - if (status.step >= DocPeerStep.Synced) { - resolve(); - } - }); - }), - new Promise((_, reject) => { - if (abort?.aborted) { - reject(abort?.reason); - } - abort?.addEventListener('abort', () => { - reject(abort.reason); - }); - }), - ]); } + await Promise.race([ + new Promise(resolve => { + this.onStatusChange.subscribe(status => { + if (status.step === DocPeerStep.Synced) { + resolve(); + } + }); + }), + new Promise((_, reject) => { + if (abort?.aborted) { + reject(abort.reason); + } + abort?.addEventListener('abort', () => { + reject(abort.reason); + }); + }), + ]); + throwIfAborted(abort); } } diff --git a/blocksuite/integration-test/package.json b/blocksuite/integration-test/package.json index faef526d45..ba841b100d 100644 --- a/blocksuite/integration-test/package.json +++ b/blocksuite/integration-test/package.json @@ -22,6 +22,7 @@ "@toeverything/theme": "^1.1.12", "@vanilla-extract/css": "^1.17.0", "lit": "^3.2.0", + "rxjs": "^7.8.1", "yjs": "^13.6.21", "zod": "^3.23.8" }, diff --git a/blocksuite/integration-test/src/__tests__/edgeless/surface-model.spec.ts b/blocksuite/integration-test/src/__tests__/edgeless/surface-model.spec.ts index 127684708d..f192cb7fbe 100644 --- a/blocksuite/integration-test/src/__tests__/edgeless/surface-model.spec.ts +++ b/blocksuite/integration-test/src/__tests__/edgeless/surface-model.spec.ts @@ -355,7 +355,10 @@ describe('stash/pop', () => { elementModel.stash('strokeWidth'); const onchange = vi.fn(); - model.elementUpdated.once(({ id }) => onchange(id)); + const subscription = model.elementUpdated.subscribe(({ id }) => { + subscription.unsubscribe(); + onchange(id); + }); elementModel.strokeWidth = 10; expect(onchange).toHaveBeenCalledWith(id); @@ -449,7 +452,10 @@ describe('local decorator', () => { const onchange = vi.fn(); - model.elementUpdated.once(({ id }) => onchange(id)); + const subscription = model.elementUpdated.subscribe(({ id }) => { + subscription.unsubscribe(); + onchange(id); + }); elementModel.display = false; expect(elementModel.display).toBe(false); diff --git a/blocksuite/integration-test/src/editors/editor-container.ts b/blocksuite/integration-test/src/editors/editor-container.ts index 63afa8b273..e9869390fe 100644 --- a/blocksuite/integration-test/src/editors/editor-container.ts +++ b/blocksuite/integration-test/src/editors/editor-container.ts @@ -159,7 +159,7 @@ export class TestAffineEditorContainer extends SignalWatcher( super.connectedCallback(); this._disposables.add( - this.doc.slots.rootAdded.on(() => this.requestUpdate()) + this.doc.slots.rootAdded.subscribe(() => this.requestUpdate()) ); } diff --git a/blocksuite/playground/apps/_common/components/docs-panel.ts b/blocksuite/playground/apps/_common/components/docs-panel.ts index 594f0147ac..4efcc9dccb 100644 --- a/blocksuite/playground/apps/_common/components/docs-panel.ts +++ b/blocksuite/playground/apps/_common/components/docs-panel.ts @@ -108,7 +108,7 @@ export class DocsPanel extends WithDisposable(ShadowlessElement) { }); this.disposables.add( - this.editor.doc.workspace.slots.docListUpdated.on(() => { + this.editor.doc.workspace.slots.docListUpdated.subscribe(() => { this.requestUpdate(); }) ); diff --git a/blocksuite/playground/apps/_common/components/starter-debug-menu.ts b/blocksuite/playground/apps/_common/components/starter-debug-menu.ts index af1db36856..2cabd299fc 100644 --- a/blocksuite/playground/apps/_common/components/starter-debug-menu.ts +++ b/blocksuite/playground/apps/_common/components/starter-debug-menu.ts @@ -732,7 +732,7 @@ export class StarterDebugMenu extends ShadowlessElement { } override firstUpdated() { - this.doc.slots.historyUpdated.on(() => { + this.doc.slots.historyUpdated.subscribe(() => { this._canUndo = this.doc.canUndo; this._canRedo = this.doc.canRedo; }); diff --git a/blocksuite/playground/apps/_common/mock-services.ts b/blocksuite/playground/apps/_common/mock-services.ts index af78cf0173..f194380b4e 100644 --- a/blocksuite/playground/apps/_common/mock-services.ts +++ b/blocksuite/playground/apps/_common/mock-services.ts @@ -1,5 +1,4 @@ import { toast } from '@blocksuite/affine/components/toast'; -import { Slot } from '@blocksuite/affine/global/slot'; import { ColorScheme, type DocMode, @@ -17,6 +16,7 @@ import { import { type Workspace } from '@blocksuite/affine/store'; import type { TestAffineEditorContainer } from '@blocksuite/integration-test'; import { Signal, signal } from '@preact/signals-core'; +import { Subject } from 'rxjs'; function getModeFromStorage() { const mapJson = localStorage.getItem('playground:docMode'); @@ -37,7 +37,7 @@ export function removeModeFromStorage(docId: string) { } const DEFAULT_MODE: DocMode = 'page'; -const slotMap = new Map>(); +const slotMap = new Map>(); export function mockDocModeService(editor: TestAffineEditorContainer) { const getEditorModeCallback: () => DocMode = () => editor.mode; @@ -54,9 +54,9 @@ export function mockDocModeService(editor: TestAffineEditorContainer) { }, onPrimaryModeChange: (handler: (mode: DocMode) => void, docId: string) => { if (!slotMap.get(docId)) { - slotMap.set(docId, new Slot()); + slotMap.set(docId, new Subject()); } - return slotMap.get(docId)!.on(handler); + return slotMap.get(docId)!.subscribe(handler); }, getEditorMode: () => { return getEditorModeCallback(); @@ -68,7 +68,7 @@ export function mockDocModeService(editor: TestAffineEditorContainer) { const modeMap = getModeFromStorage(); modeMap.set(docId, mode); saveModeToStorage(modeMap); - slotMap.get(docId)?.emit(mode); + slotMap.get(docId)?.next(mode); }, togglePrimaryMode: (docId: string) => { const mode = diff --git a/blocksuite/playground/apps/starter/utils/extensions.ts b/blocksuite/playground/apps/starter/utils/extensions.ts index 9cddb81181..54896af546 100644 --- a/blocksuite/playground/apps/starter/utils/extensions.ts +++ b/blocksuite/playground/apps/starter/utils/extensions.ts @@ -51,7 +51,7 @@ export function createTestEditor(store: Store, workspace: Workspace) { editor.std .get(RefNodeSlotsProvider) - .docLinkClicked.on(({ pageId: docId }) => { + .docLinkClicked.subscribe(({ pageId: docId }) => { const target = workspace.getDoc(docId); if (!target) { throw new Error(`Failed to jump to doc ${docId}`); diff --git a/blocksuite/playground/apps/starter/utils/test.ts b/blocksuite/playground/apps/starter/utils/test.ts index 464da5dfd1..8cfb5218a6 100644 --- a/blocksuite/playground/apps/starter/utils/test.ts +++ b/blocksuite/playground/apps/starter/utils/test.ts @@ -9,7 +9,12 @@ export async function prepareTestApp(collection: Workspace) { const store = await getStore(collection, noInit); store.load(); if (!store.root) { - await new Promise(resolve => store.slots.rootAdded.once(resolve)); + await new Promise(resolve => { + const subscription = store.slots.rootAdded.subscribe(value => { + subscription.unsubscribe(); + resolve(value); + }); + }); } await createTestApp(store, collection); @@ -34,7 +39,7 @@ async function getStore( } const { resolve, reject, promise } = Promise.withResolvers(); - collection.slots.docListUpdated.on(() => { + collection.slots.docListUpdated.subscribe(() => { const doc = collection.docs.values().next().value; const firstDoc = doc?.getStore(); if (!firstDoc) { diff --git a/blocksuite/playground/examples/inline/test-page.ts b/blocksuite/playground/examples/inline/test-page.ts index ad9f9944dd..01310f8b22 100644 --- a/blocksuite/playground/examples/inline/test-page.ts +++ b/blocksuite/playground/examples/inline/test-page.ts @@ -128,7 +128,7 @@ export class TestRichText extends ShadowlessElement { this.style.outline = 'none'; this.inlineEditor.mount(this._container, this); - this.inlineEditor.slots.textChange.on(() => { + this.inlineEditor.slots.textChange.subscribe(() => { const el = this.querySelector('.y-text'); if (el) { const text = this.inlineEditor.yText.toDelta(); diff --git a/blocksuite/playground/package.json b/blocksuite/playground/package.json index db686f8518..af43495e1b 100644 --- a/blocksuite/playground/package.json +++ b/blocksuite/playground/package.json @@ -26,6 +26,7 @@ "jszip": "^3.10.1", "lit": "^3.2.0", "lz-string": "^1.5.0", + "rxjs": "^7.8.1", "tweakpane": "^4.0.4", "y-indexeddb": "^9.0.12", "y-protocols": "^1.0.6", diff --git a/blocksuite/tests-legacy/package.json b/blocksuite/tests-legacy/package.json index 823b4fc6e6..5551d416e6 100644 --- a/blocksuite/tests-legacy/package.json +++ b/blocksuite/tests-legacy/package.json @@ -10,7 +10,8 @@ "@blocksuite/affine": "workspace:*", "@blocksuite/integration-test": "workspace:*", "@playwright/test": "=1.51.0", - "@toeverything/theme": "^1.1.12" + "@toeverything/theme": "^1.1.12", + "rxjs": "^7.8.1" }, "bsImport": { "@atlaskit/pragmatic-drag-and-drop/element/adapter": "@atlaskit/pragmatic-drag-and-drop/dist/cjs/entry-point/element/adapter.js", diff --git a/packages/frontend/core/src/blocksuite/ai/_common/chat-actions-handle.ts b/packages/frontend/core/src/blocksuite/ai/_common/chat-actions-handle.ts index 922080047e..832f133bee 100644 --- a/packages/frontend/core/src/blocksuite/ai/_common/chat-actions-handle.ts +++ b/packages/frontend/core/src/blocksuite/ai/_common/chat-actions-handle.ts @@ -441,7 +441,7 @@ const CREATE_AS_DOC = { newDoc.addBlock('affine:surface', {}, rootId); const noteId = newDoc.addBlock('affine:note', {}, rootId); - host.std.getOptional(RefNodeSlotsProvider)?.docLinkClicked.emit({ + host.std.getOptional(RefNodeSlotsProvider)?.docLinkClicked.next({ pageId: newDoc.id, host, }); diff --git a/packages/frontend/core/src/blocksuite/ai/_common/config.ts b/packages/frontend/core/src/blocksuite/ai/_common/config.ts index b2c9a7b228..dc1f981fb6 100644 --- a/packages/frontend/core/src/blocksuite/ai/_common/config.ts +++ b/packages/frontend/core/src/blocksuite/ai/_common/config.ts @@ -341,7 +341,7 @@ const OthersAIGroup: AIItemGroupConfig = { icon: CommentIcon(), handler: host => { const panel = getAIPanelWidget(host); - AIProvider.slots.requestOpenWithChat.emit({ + AIProvider.slots.requestOpenWithChat.next({ host, autoSelect: true, }); diff --git a/packages/frontend/core/src/blocksuite/ai/actions/edgeless-response.ts b/packages/frontend/core/src/blocksuite/ai/actions/edgeless-response.ts index b150d698bd..01decfec0b 100644 --- a/packages/frontend/core/src/blocksuite/ai/actions/edgeless-response.ts +++ b/packages/frontend/core/src/blocksuite/ai/actions/edgeless-response.ts @@ -565,7 +565,7 @@ export function actionToResponse( handler: () => { reportResponse('result:continue-in-chat'); const panel = getAIPanelWidget(host); - AIProvider.slots.requestOpenWithChat.emit({ host }); + AIProvider.slots.requestOpenWithChat.next({ host }); panel.hide(); }, }, @@ -604,11 +604,11 @@ export function actionToErrorResponse< ): ErrorConfig { return { upgrade: () => { - AIProvider.slots.requestUpgradePlan.emit({ host: panel.host }); + AIProvider.slots.requestUpgradePlan.next({ host: panel.host }); panel.hide(); }, login: () => { - AIProvider.slots.requestLogin.emit({ host: panel.host }); + AIProvider.slots.requestLogin.next({ host: panel.host }); panel.hide(); }, cancel: () => { diff --git a/packages/frontend/core/src/blocksuite/ai/ai-panel.ts b/packages/frontend/core/src/blocksuite/ai/ai-panel.ts index a1da843e7f..10a91c8a80 100644 --- a/packages/frontend/core/src/blocksuite/ai/ai-panel.ts +++ b/packages/frontend/core/src/blocksuite/ai/ai-panel.ts @@ -193,7 +193,7 @@ function buildPageResponseConfig( icon: ChatWithAiIcon(), handler: () => { reportResponse('result:continue-in-chat'); - AIProvider.slots.requestOpenWithChat.emit({ host }); + AIProvider.slots.requestOpenWithChat.next({ host }); panel.hide(); }, }, @@ -258,11 +258,11 @@ export function buildFinishConfig( export function buildErrorConfig(panel: AffineAIPanelWidget) { return { upgrade: () => { - AIProvider.slots.requestUpgradePlan.emit({ host: panel.host }); + AIProvider.slots.requestUpgradePlan.next({ host: panel.host }); panel.hide(); }, login: () => { - AIProvider.slots.requestLogin.emit({ host: panel.host }); + AIProvider.slots.requestLogin.next({ host: panel.host }); panel.hide(); }, cancel: () => { diff --git a/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-panel-input.ts b/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-panel-input.ts index a3458dd78d..24979e1606 100644 --- a/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-panel-input.ts +++ b/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-panel-input.ts @@ -273,12 +273,16 @@ export class ChatPanelInput extends SignalWatcher(WithDisposable(LitElement)) { super.connectedCallback(); this._disposables.add( - AIProvider.slots.requestSendWithChat.on( - async ({ input, context, host }) => { + AIProvider.slots.requestSendWithChat.subscribe( + ({ input, context, host }) => { if (this.host === host) { context && this.updateContext(context); - await this.updateComplete; - await this.send(input); + const { updateComplete, send } = this; + updateComplete + .then(() => { + return send(input); + }) + .catch(console.error); } } ) diff --git a/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-panel-messages.ts b/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-panel-messages.ts index fa66a4f4da..6b98435a33 100644 --- a/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-panel-messages.ts +++ b/packages/frontend/core/src/blocksuite/ai/chat-panel/chat-panel-messages.ts @@ -316,7 +316,7 @@ export class ChatPanelMessages extends WithDisposable(ShadowlessElement) { .catch(console.error); disposables.add( - AIProvider.slots.userInfo.on(userInfo => { + AIProvider.slots.userInfo.subscribe(userInfo => { const { status, error } = this.chatContextValue; this.avatarUrl = userInfo?.avatarUrl ?? ''; if ( @@ -329,7 +329,7 @@ export class ChatPanelMessages extends WithDisposable(ShadowlessElement) { }) ); disposables.add( - this.host.selection.slots.changed.on(() => { + this.host.selection.slots.changed.subscribe(() => { this._selectionValue = this.host.selection.value; }) ); diff --git a/packages/frontend/core/src/blocksuite/ai/chat-panel/components/doc-chip.ts b/packages/frontend/core/src/blocksuite/ai/chat-panel/components/doc-chip.ts index 340ae61908..d85b77b3c1 100644 --- a/packages/frontend/core/src/blocksuite/ai/chat-panel/components/doc-chip.ts +++ b/packages/frontend/core/src/blocksuite/ai/chat-panel/components/doc-chip.ts @@ -54,7 +54,7 @@ export class ChatPanelDocChip extends SignalWatcher( const doc = this.docDisplayConfig.getDoc(this.chip.docId); if (doc) { this.disposables.add( - doc.slots.blockUpdated.on( + doc.slots.blockUpdated.subscribe( throttle(this.autoUpdateChip, EXTRACT_DOC_THROTTLE) ) ); diff --git a/packages/frontend/core/src/blocksuite/ai/chat-panel/index.ts b/packages/frontend/core/src/blocksuite/ai/chat-panel/index.ts index a4289b2ae2..23bc172380 100644 --- a/packages/frontend/core/src/blocksuite/ai/chat-panel/index.ts +++ b/packages/frontend/core/src/blocksuite/ai/chat-panel/index.ts @@ -392,7 +392,7 @@ export class ChatPanel extends SignalWatcher( if (!this.doc) throw new Error('doc is required'); this._disposables.add( - AIProvider.slots.actions.on(({ event }) => { + AIProvider.slots.actions.subscribe(({ event }) => { const { status } = this.chatContextValue; if ( event === 'finished' && @@ -403,16 +403,19 @@ export class ChatPanel extends SignalWatcher( }) ); this._disposables.add( - AIProvider.slots.userInfo.on(async () => { - await this._initPanel(); + AIProvider.slots.userInfo.subscribe(() => { + this._initPanel().catch(console.error); }) ); this._disposables.add( - AIProvider.slots.requestOpenWithChat.on(async ({ host }) => { + AIProvider.slots.requestOpenWithChat.subscribe(({ host }) => { if (this.host === host) { - const context = await extractSelectedContent(host); - if (!context) return; - this.updateContext(context); + extractSelectedContent(host) + .then(context => { + if (!context) return; + this.updateContext(context); + }) + .catch(console.error); } }) ); diff --git a/packages/frontend/core/src/blocksuite/ai/chat-panel/preload-config.ts b/packages/frontend/core/src/blocksuite/ai/chat-panel/preload-config.ts index 18ea125538..9d35b25531 100644 --- a/packages/frontend/core/src/blocksuite/ai/chat-panel/preload-config.ts +++ b/packages/frontend/core/src/blocksuite/ai/chat-panel/preload-config.ts @@ -18,7 +18,7 @@ export const AIPreloadConfig = [ icon: LanguageIcon(), text: 'Read a foreign language article with AI', handler: () => { - AIProvider.slots.requestInsertTemplate.emit({ + AIProvider.slots.requestInsertTemplate.next({ template: readAforeign, mode: 'edgeless', }); @@ -28,7 +28,7 @@ export const AIPreloadConfig = [ icon: MindmapIcon(), text: 'Tidy an article with AI MindMap Action', handler: () => { - AIProvider.slots.requestInsertTemplate.emit({ + AIProvider.slots.requestInsertTemplate.next({ template: TidyMindMapV3, mode: 'edgeless', }); @@ -38,7 +38,7 @@ export const AIPreloadConfig = [ icon: ImageIcon(), text: 'Add illustrations to the article', handler: () => { - AIProvider.slots.requestInsertTemplate.emit({ + AIProvider.slots.requestInsertTemplate.next({ template: redHat, mode: 'edgeless', }); @@ -48,7 +48,7 @@ export const AIPreloadConfig = [ icon: PenIcon(), text: 'Complete writing with AI', handler: () => { - AIProvider.slots.requestInsertTemplate.emit({ + AIProvider.slots.requestInsertTemplate.next({ template: completeWritingWithAI, mode: 'edgeless', }); @@ -58,7 +58,7 @@ export const AIPreloadConfig = [ icon: SendIcon(), text: 'Freely communicate with AI', handler: () => { - AIProvider.slots.requestInsertTemplate.emit({ + AIProvider.slots.requestInsertTemplate.next({ template: freelyCommunicateWithAI, mode: 'edgeless', }); diff --git a/packages/frontend/core/src/blocksuite/ai/components/ask-ai-toolbar.ts b/packages/frontend/core/src/blocksuite/ai/components/ask-ai-toolbar.ts index 93dfad832f..97386b6c56 100644 --- a/packages/frontend/core/src/blocksuite/ai/components/ask-ai-toolbar.ts +++ b/packages/frontend/core/src/blocksuite/ai/components/ask-ai-toolbar.ts @@ -75,7 +75,7 @@ export class AskAIToolbarButton extends WithDisposable(LitElement) { aiPanel.hide(); extractSelectedContent(this.host) .then(context => { - AIProvider.slots.requestSendWithChat.emit({ + AIProvider.slots.requestSendWithChat.next({ input, context, host: this.host, diff --git a/packages/frontend/core/src/blocksuite/ai/entries/edgeless/actions-config.ts b/packages/frontend/core/src/blocksuite/ai/entries/edgeless/actions-config.ts index 38e476987c..65980403ef 100644 --- a/packages/frontend/core/src/blocksuite/ai/entries/edgeless/actions-config.ts +++ b/packages/frontend/core/src/blocksuite/ai/entries/edgeless/actions-config.ts @@ -107,7 +107,7 @@ const othersGroup: AIItemGroupConfig = { showWhen: () => true, handler: host => { const panel = getAIPanelWidget(host); - AIProvider.slots.requestOpenWithChat.emit({ + AIProvider.slots.requestOpenWithChat.next({ host, mode: 'edgeless', autoSelect: true, diff --git a/packages/frontend/core/src/blocksuite/ai/entries/edgeless/index.ts b/packages/frontend/core/src/blocksuite/ai/entries/edgeless/index.ts index e001443547..8f0182d2a1 100644 --- a/packages/frontend/core/src/blocksuite/ai/entries/edgeless/index.ts +++ b/packages/frontend/core/src/blocksuite/ai/entries/edgeless/index.ts @@ -50,7 +50,7 @@ export function setupEdgelessElementToolbarAIEntry( aiPanel.hide(); extractSelectedContent(edgeless.host) .then(context => { - AIProvider.slots.requestSendWithChat.emit({ + AIProvider.slots.requestSendWithChat.next({ input, context, host: edgeless.host, diff --git a/packages/frontend/core/src/blocksuite/ai/extensions/ai-code.ts b/packages/frontend/core/src/blocksuite/ai/extensions/ai-code.ts index ab7d15eedb..91dba9d8b4 100644 --- a/packages/frontend/core/src/blocksuite/ai/extensions/ai-code.ts +++ b/packages/frontend/core/src/blocksuite/ai/extensions/ai-code.ts @@ -13,7 +13,7 @@ class AICodeBlockWatcher extends LifeCycleWatcher { override mounted() { super.mounted(); const { view } = this.std; - view.viewUpdated.on(payload => { + view.viewUpdated.subscribe(payload => { if (payload.type !== 'widget' || payload.method !== 'add') { return; } diff --git a/packages/frontend/core/src/blocksuite/ai/extensions/ai-edgeless-root.ts b/packages/frontend/core/src/blocksuite/ai/extensions/ai-edgeless-root.ts index e053dd291e..300038d81e 100644 --- a/packages/frontend/core/src/blocksuite/ai/extensions/ai-edgeless-root.ts +++ b/packages/frontend/core/src/blocksuite/ai/extensions/ai-edgeless-root.ts @@ -52,7 +52,7 @@ function getAIEdgelessRootWatcher(framework: FrameworkProvider) { override mounted() { super.mounted(); const { view } = this.std; - view.viewUpdated.on(payload => { + view.viewUpdated.subscribe(payload => { if (payload.type !== 'widget' || payload.method !== 'add') { return; } diff --git a/packages/frontend/core/src/blocksuite/ai/extensions/ai-image.ts b/packages/frontend/core/src/blocksuite/ai/extensions/ai-image.ts index 95fa9635a3..7180525284 100644 --- a/packages/frontend/core/src/blocksuite/ai/extensions/ai-image.ts +++ b/packages/frontend/core/src/blocksuite/ai/extensions/ai-image.ts @@ -11,7 +11,7 @@ class AIImageBlockWatcher extends LifeCycleWatcher { override mounted() { super.mounted(); const { view } = this.std; - view.viewUpdated.on(payload => { + view.viewUpdated.subscribe(payload => { if (payload.type !== 'widget' || payload.method !== 'add') { return; } diff --git a/packages/frontend/core/src/blocksuite/ai/extensions/ai-page-root.ts b/packages/frontend/core/src/blocksuite/ai/extensions/ai-page-root.ts index 46149f615f..ff820b030c 100644 --- a/packages/frontend/core/src/blocksuite/ai/extensions/ai-page-root.ts +++ b/packages/frontend/core/src/blocksuite/ai/extensions/ai-page-root.ts @@ -23,7 +23,7 @@ function getAIPageRootWatcher(framework: FrameworkProvider) { override mounted() { super.mounted(); const { view } = this.std; - view.viewUpdated.on(payload => { + view.viewUpdated.subscribe(payload => { if (payload.type !== 'widget' || payload.method !== 'add') { return; } diff --git a/packages/frontend/core/src/blocksuite/ai/messages/error.ts b/packages/frontend/core/src/blocksuite/ai/messages/error.ts index aa8ff572f5..fb0e6574dd 100644 --- a/packages/frontend/core/src/blocksuite/ai/messages/error.ts +++ b/packages/frontend/core/src/blocksuite/ai/messages/error.ts @@ -188,7 +188,7 @@ const PaymentRequiredErrorRenderer = (host: EditorHost) => html` AIProvider.slots.requestUpgradePlan.emit({ host })} + .onClick=${() => AIProvider.slots.requestUpgradePlan.next({ host })} > `; @@ -196,7 +196,7 @@ const LoginRequiredErrorRenderer = (host: EditorHost) => html` AIProvider.slots.requestLogin.emit({ host })} + .onClick=${() => AIProvider.slots.requestLogin.next({ host })} > `; diff --git a/packages/frontend/core/src/blocksuite/ai/mini-mindmap/mindmap-service.ts b/packages/frontend/core/src/blocksuite/ai/mini-mindmap/mindmap-service.ts index 2fe57e6635..b878bf4ba2 100644 --- a/packages/frontend/core/src/blocksuite/ai/mini-mindmap/mindmap-service.ts +++ b/packages/frontend/core/src/blocksuite/ai/mini-mindmap/mindmap-service.ts @@ -1,14 +1,15 @@ import { BlockService } from '@blocksuite/affine/block-std'; -import { Slot } from '@blocksuite/affine/global/slot'; import { RootBlockSchema } from '@blocksuite/affine/model'; +import { Subject } from 'rxjs'; export class MindmapService extends BlockService { static override readonly flavour = RootBlockSchema.model.flavour; - requestCenter = new Slot(); + // eslint-disable-next-line rxjs/finnish + requestCenter = new Subject(); center() { - this.requestCenter.emit(); + this.requestCenter.next(); } override mounted(): void {} diff --git a/packages/frontend/core/src/blocksuite/ai/mini-mindmap/surface-block.ts b/packages/frontend/core/src/blocksuite/ai/mini-mindmap/surface-block.ts index e0cfe7d895..6f59ed4647 100644 --- a/packages/frontend/core/src/blocksuite/ai/mini-mindmap/surface-block.ts +++ b/packages/frontend/core/src/blocksuite/ai/mini-mindmap/surface-block.ts @@ -65,7 +65,7 @@ export class MindmapSurfaceBlock extends BlockComponent { private _setupCenterEffect() { this._disposables.add( - this.mindmapService.requestCenter.on(() => { + this.mindmapService.requestCenter.subscribe(() => { let bound: Bound; this.model.elementModels.forEach(el => { @@ -85,7 +85,7 @@ export class MindmapSurfaceBlock extends BlockComponent { private _setupRenderer() { this._disposables.add( - this.model.elementUpdated.on(() => { + this.model.elementUpdated.subscribe(() => { this.mindmapService.center(); }) ); diff --git a/packages/frontend/core/src/blocksuite/ai/provider/ai-provider.ts b/packages/frontend/core/src/blocksuite/ai/provider/ai-provider.ts index 7ff4bc9764..44123ed659 100644 --- a/packages/frontend/core/src/blocksuite/ai/provider/ai-provider.ts +++ b/packages/frontend/core/src/blocksuite/ai/provider/ai-provider.ts @@ -1,6 +1,6 @@ import type { EditorHost } from '@blocksuite/affine/block-std'; -import { Slot } from '@blocksuite/affine/global/slot'; import { captureException } from '@sentry/react'; +import { Subject } from 'rxjs'; import type { ChatContextValue } from '../chat-panel/chat-context'; import { @@ -123,22 +123,24 @@ export class AIProvider { private readonly slots = { // use case: when user selects "continue in chat" in an ask ai result panel // do we need to pass the context to the chat panel? - requestOpenWithChat: new Slot(), - requestSendWithChat: new Slot(), - requestInsertTemplate: new Slot<{ + /* eslint-disable rxjs/finnish */ + requestOpenWithChat: new Subject(), + requestSendWithChat: new Subject(), + requestInsertTemplate: new Subject<{ template: string; mode: 'page' | 'edgeless'; }>(), - requestLogin: new Slot<{ host: EditorHost }>(), - requestUpgradePlan: new Slot<{ host: EditorHost }>(), + requestLogin: new Subject<{ host: EditorHost }>(), + requestUpgradePlan: new Subject<{ host: EditorHost }>(), // stream of AI actions triggered by users - actions: new Slot<{ + actions: new Subject<{ action: keyof BlockSuitePresets.AIActions; options: BlockSuitePresets.AITextActionOptions; event: ActionEventType; }>(), // downstream can emit this slot to notify ai presets that user info has been updated - userInfo: new Slot(), + userInfo: new Subject(), + /* eslint-enable rxjs/finnish */ }; // track the history of triggered actions (in memory only) @@ -162,7 +164,7 @@ export class AIProvider { ) => { const options = args[0]; const slots = this.slots; - slots.actions.emit({ + slots.actions.next({ action: id, options, event: 'started', @@ -186,31 +188,31 @@ export class AIProvider { try { user = await AIProvider.userInfo; yield* result; - slots.actions.emit({ + slots.actions.next({ action: id, options, event: 'finished', }); } catch (err) { - slots.actions.emit({ + slots.actions.next({ action: id, options, event: 'error', }); if (err instanceof PaymentRequiredError) { - slots.actions.emit({ + slots.actions.next({ action: id, options, event: 'aborted:paywall', }); } else if (err instanceof UnauthorizedError) { - slots.actions.emit({ + slots.actions.next({ action: id, options, event: 'aborted:login-required', }); } else { - slots.actions.emit({ + slots.actions.next({ action: id, options, event: 'aborted:server-error', @@ -232,7 +234,7 @@ export class AIProvider { return result .then(async result => { user = await AIProvider.userInfo; - slots.actions.emit({ + slots.actions.next({ action: id, options, event: 'finished', @@ -240,13 +242,13 @@ export class AIProvider { return result; }) .catch(err => { - slots.actions.emit({ + slots.actions.next({ action: id, options, event: 'error', }); if (err instanceof PaymentRequiredError) { - slots.actions.emit({ + slots.actions.next({ action: id, options, event: 'aborted:paywall', diff --git a/packages/frontend/core/src/blocksuite/ai/provider/setup-provider.tsx b/packages/frontend/core/src/blocksuite/ai/provider/setup-provider.tsx index e45579472c..04ff2f8fc9 100644 --- a/packages/frontend/core/src/blocksuite/ai/provider/setup-provider.tsx +++ b/packages/frontend/core/src/blocksuite/ai/provider/setup-provider.tsx @@ -527,13 +527,15 @@ Could you make a new website based on these notes and send back just the html fi return client.forkSession(options); }); - const disposeRequestLoginHandler = AIProvider.slots.requestLogin.on(() => { - globalDialogService.open('sign-in', {}); - }); + const disposeRequestLoginHandler = AIProvider.slots.requestLogin.subscribe( + () => { + globalDialogService.open('sign-in', {}); + } + ); setupTracker(); return () => { - disposeRequestLoginHandler.dispose(); + disposeRequestLoginHandler.unsubscribe(); }; } diff --git a/packages/frontend/core/src/blocksuite/ai/provider/tracker.ts b/packages/frontend/core/src/blocksuite/ai/provider/tracker.ts index 8037e98152..7bcdd639d7 100644 --- a/packages/frontend/core/src/blocksuite/ai/provider/tracker.ts +++ b/packages/frontend/core/src/blocksuite/ai/provider/tracker.ts @@ -3,6 +3,7 @@ import type { EditorHost } from '@blocksuite/affine/block-std'; import type { GfxPrimitiveElementModel } from '@blocksuite/affine/block-std/gfx'; import type { BlockModel } from '@blocksuite/affine/store'; import { lowerCase, omit } from 'lodash-es'; +import type { Subject } from 'rxjs'; import { AIProvider } from './ai-provider'; @@ -60,9 +61,9 @@ type AIActionEventProperties = { workspaceId: string; }; -type BlocksuiteActionEvent = Parameters< - Parameters[0] ->[0]; +type SubjectValue = T extends Subject ? U : never; + +type BlocksuiteActionEvent = SubjectValue; const trackAction = ({ eventName, @@ -252,15 +253,15 @@ const toTrackedOptions = ( }; export function setupTracker() { - AIProvider.slots.requestUpgradePlan.on(() => { + AIProvider.slots.requestUpgradePlan.subscribe(() => { track.$.paywall.aiAction.viewPlans(); }); - AIProvider.slots.requestLogin.on(() => { + AIProvider.slots.requestLogin.subscribe(() => { track.doc.editor.aiActions.requestSignIn(); }); - AIProvider.slots.actions.on(event => { + AIProvider.slots.actions.subscribe(event => { const properties = toTrackedOptions(event); if (properties) { trackAction(properties); diff --git a/packages/frontend/core/src/blocksuite/ai/tool/copilot-tool.ts b/packages/frontend/core/src/blocksuite/ai/tool/copilot-tool.ts index f07b5827f5..04ce322985 100644 --- a/packages/frontend/core/src/blocksuite/ai/tool/copilot-tool.ts +++ b/packages/frontend/core/src/blocksuite/ai/tool/copilot-tool.ts @@ -10,7 +10,7 @@ import { Bound, getCommonBoundWithRotation, } from '@blocksuite/affine/global/gfx'; -import { Slot } from '@blocksuite/affine/global/slot'; +import { Subject } from 'rxjs'; import { AFFINE_AI_PANEL_WIDGET, @@ -22,7 +22,8 @@ export class CopilotTool extends BaseTool { private _dragging = false; - draggingAreaUpdated = new Slot(); + // eslint-disable-next-line rxjs/finnish + draggingAreaUpdated = new Subject(); dragLastPoint: [number, number] = [0, 0]; @@ -85,7 +86,7 @@ export class CopilotTool extends BaseTool { if (!this._dragging) return; this._dragging = false; - this.draggingAreaUpdated.emit(true); + this.draggingAreaUpdated.next(true); } override dragMove(e: PointerEventState): void { @@ -108,7 +109,7 @@ export class CopilotTool extends BaseTool { }); } - this.draggingAreaUpdated.emit(); + this.draggingAreaUpdated.next(); } override dragStart(e: PointerEventState): void { @@ -116,7 +117,7 @@ export class CopilotTool extends BaseTool { this._initDragState(e); this._dragging = true; - this.draggingAreaUpdated.emit(); + this.draggingAreaUpdated.next(); } override mounted(): void { @@ -167,7 +168,7 @@ export class CopilotTool extends BaseTool { inoperable: true, }); - this.draggingAreaUpdated.emit(true); + this.draggingAreaUpdated.next(true); } } diff --git a/packages/frontend/core/src/blocksuite/ai/utils/action-reporter.ts b/packages/frontend/core/src/blocksuite/ai/utils/action-reporter.ts index 8ceb374020..4257879ef0 100644 --- a/packages/frontend/core/src/blocksuite/ai/utils/action-reporter.ts +++ b/packages/frontend/core/src/blocksuite/ai/utils/action-reporter.ts @@ -4,7 +4,7 @@ export function reportResponse(event: ActionEventType) { const lastAction = AIProvider.actionHistory.at(-1); if (!lastAction) return; - AIProvider.slots.actions.emit({ + AIProvider.slots.actions.next({ action: lastAction.action, options: lastAction.options, event, diff --git a/packages/frontend/core/src/blocksuite/ai/widgets/edgeless-copilot/index.ts b/packages/frontend/core/src/blocksuite/ai/widgets/edgeless-copilot/index.ts index 0e65653136..bdc3f9d12a 100644 --- a/packages/frontend/core/src/blocksuite/ai/widgets/edgeless-copilot/index.ts +++ b/packages/frontend/core/src/blocksuite/ai/widgets/edgeless-copilot/index.ts @@ -200,7 +200,7 @@ export class EdgelessCopilotWidget extends WidgetComponent { const CopilotSelectionTool = this.gfx.tool.get('copilot'); this._disposables.add( - CopilotSelectionTool.draggingAreaUpdated.on(shouldShowPanel => { + CopilotSelectionTool.draggingAreaUpdated.subscribe(shouldShowPanel => { this._visible = true; this._updateSelection(CopilotSelectionTool.area); if (shouldShowPanel) { @@ -213,7 +213,7 @@ export class EdgelessCopilotWidget extends WidgetComponent { ); this._disposables.add( - this.gfx.viewport.viewportUpdated.on(() => { + this.gfx.viewport.viewportUpdated.subscribe(() => { if (!this._visible) return; this._updateSelection(CopilotSelectionTool.area); @@ -258,7 +258,7 @@ export class EdgelessCopilotWidget extends WidgetComponent { lockToolbar(disabled: boolean) { const legacySlot = this.std.get(EdgelessLegacySlotIdentifier); - legacySlot.toolbarLocked.emit(disabled); + legacySlot.toolbarLocked.next(disabled); } override render() { diff --git a/packages/frontend/core/src/blocksuite/block-suite-editor/blocksuite-editor.tsx b/packages/frontend/core/src/blocksuite/block-suite-editor/blocksuite-editor.tsx index b3db10de58..34ee1acc1c 100644 --- a/packages/frontend/core/src/blocksuite/block-suite-editor/blocksuite-editor.tsx +++ b/packages/frontend/core/src/blocksuite/block-suite-editor/blocksuite-editor.tsx @@ -9,7 +9,7 @@ import { customImageProxyMiddleware, ImageProxyService, } from '@blocksuite/affine/blocks/image'; -import { DisposableGroup } from '@blocksuite/affine/global/slot'; +import { DisposableGroup } from '@blocksuite/affine/global/disposable'; import type { DocMode } from '@blocksuite/affine/model'; import { LinkPreviewerService } from '@blocksuite/affine/shared/services'; import type { Store } from '@blocksuite/affine/store'; @@ -49,13 +49,14 @@ const BlockSuiteEditorImpl = ({ defaultOpenProperty, }: EditorProps) => { useEffect(() => { - const disposable = page.slots.blockUpdated.once(() => { + const disposable = page.slots.blockUpdated.subscribe(() => { + disposable.unsubscribe(); page.workspace.meta.setDocMeta(page.id, { updatedDate: Date.now(), }); }); return () => { - disposable.dispose(); + disposable.unsubscribe(); }; }, [page]); @@ -154,15 +155,16 @@ export const BlockSuiteEditor = (props: EditorProps) => { return; } const timer = setTimeout(() => { - disposable.dispose(); + disposable.unsubscribe(); setError(new NoPageRootError(props.page)); }, 20 * 1000); - const disposable = props.page.slots.rootAdded.once(() => { + const disposable = props.page.slots.rootAdded.subscribe(() => { + disposable.unsubscribe(); setIsLoading(false); clearTimeout(timer); }); return () => { - disposable.dispose(); + disposable.unsubscribe(); clearTimeout(timer); }; }, [props.page]); diff --git a/packages/frontend/core/src/blocksuite/block-suite-editor/starter-bar.tsx b/packages/frontend/core/src/blocksuite/block-suite-editor/starter-bar.tsx index 5591c08656..7a549aa19d 100644 --- a/packages/frontend/core/src/blocksuite/block-suite-editor/starter-bar.tsx +++ b/packages/frontend/core/src/blocksuite/block-suite-editor/starter-bar.tsx @@ -104,8 +104,11 @@ const StarterBarNotEmpty = ({ doc }: { doc: Store }) => { const { id, created } = rootComponent.focusFirstParagraph(); if (created) { - std.view.viewUpdated.once(v => { - if (v.id === id) handleInlineAskAIAction(std.host, pageAIGroups); + const subscription = std.view.viewUpdated.subscribe(v => { + if (v.id === id) { + subscription.unsubscribe(); + handleInlineAskAIAction(std.host, pageAIGroups); + } }); } else { handleInlineAskAIAction(std.host, pageAIGroups); diff --git a/packages/frontend/core/src/blocksuite/editors/edgeless-editor.ts b/packages/frontend/core/src/blocksuite/editors/edgeless-editor.ts index bcad360b08..e8db4e83e2 100644 --- a/packages/frontend/core/src/blocksuite/editors/edgeless-editor.ts +++ b/packages/frontend/core/src/blocksuite/editors/edgeless-editor.ts @@ -47,7 +47,7 @@ export class EdgelessEditor extends SignalWatcher( override connectedCallback() { super.connectedCallback(); this._disposables.add( - this.doc.slots.rootAdded.on(() => this.requestUpdate()) + this.doc.slots.rootAdded.subscribe(() => this.requestUpdate()) ); this.std = new BlockStdScope({ store: this.doc, diff --git a/packages/frontend/core/src/blocksuite/editors/page-editor.ts b/packages/frontend/core/src/blocksuite/editors/page-editor.ts index 4efabaab4e..99d9889732 100644 --- a/packages/frontend/core/src/blocksuite/editors/page-editor.ts +++ b/packages/frontend/core/src/blocksuite/editors/page-editor.ts @@ -59,7 +59,7 @@ export class PageEditor extends SignalWatcher( override connectedCallback() { super.connectedCallback(); this._disposables.add( - this.doc.slots.rootAdded.on(() => this.requestUpdate()) + this.doc.slots.rootAdded.subscribe(() => this.requestUpdate()) ); this.std = new BlockStdScope({ store: this.doc, diff --git a/packages/frontend/core/src/blocksuite/extensions/doc-mode-service.ts b/packages/frontend/core/src/blocksuite/extensions/doc-mode-service.ts index c8e2a6e083..e5d2a2ea53 100644 --- a/packages/frontend/core/src/blocksuite/extensions/doc-mode-service.ts +++ b/packages/frontend/core/src/blocksuite/extensions/doc-mode-service.ts @@ -44,9 +44,7 @@ export function patchDocModeService( ? docsService.list.primaryMode$(id) : docService.doc.primaryMode$; const sub = mode$.subscribe(m => handler((m || DEFAULT_MODE) as DocMode)); - return { - dispose: sub.unsubscribe, - }; + return sub; }; } diff --git a/packages/frontend/core/src/blocksuite/extensions/edgeless-clipboard.ts b/packages/frontend/core/src/blocksuite/extensions/edgeless-clipboard.ts index 9ba97bf680..abafd5a11b 100644 --- a/packages/frontend/core/src/blocksuite/extensions/edgeless-clipboard.ts +++ b/packages/frontend/core/src/blocksuite/extensions/edgeless-clipboard.ts @@ -9,7 +9,7 @@ export class EdgelessClipboardWatcher extends LifeCycleWatcher { override mounted() { super.mounted(); const { view } = this.std; - view.viewUpdated.on(payload => { + view.viewUpdated.subscribe(payload => { if (payload.type !== 'block' || payload.method !== 'add') { return; } diff --git a/packages/frontend/core/src/blocksuite/extensions/entry/enable-mobile.ts b/packages/frontend/core/src/blocksuite/extensions/entry/enable-mobile.ts index f9ec442447..bfb4bf53ff 100644 --- a/packages/frontend/core/src/blocksuite/extensions/entry/enable-mobile.ts +++ b/packages/frontend/core/src/blocksuite/extensions/entry/enable-mobile.ts @@ -14,7 +14,7 @@ import type { Container, ServiceIdentifier, } from '@blocksuite/affine/global/di'; -import { DisposableGroup } from '@blocksuite/affine/global/slot'; +import { DisposableGroup } from '@blocksuite/affine/global/disposable'; import { type ReferenceNodeConfig, ReferenceNodeConfigIdentifier, diff --git a/packages/frontend/core/src/blocksuite/extensions/note-config/edgeless-note-header.tsx b/packages/frontend/core/src/blocksuite/extensions/note-config/edgeless-note-header.tsx index 92e7216319..a21a22bcd4 100644 --- a/packages/frontend/core/src/blocksuite/extensions/note-config/edgeless-note-header.tsx +++ b/packages/frontend/core/src/blocksuite/extensions/note-config/edgeless-note-header.tsx @@ -57,7 +57,7 @@ const EdgelessNoteToggleButton = ({ note }: { note: NoteBlockModel }) => { const { selection } = gfx; - const dispose = selection.slots.updated.on(() => { + const dispose = selection.slots.updated.subscribe(() => { if (selection.has(note.id) && selection.editing) { note.doc.transact(() => { note.edgeless.collapse = false; @@ -65,7 +65,7 @@ const EdgelessNoteToggleButton = ({ note }: { note: NoteBlockModel }) => { } }); - return () => dispose.dispose(); + return () => dispose.unsubscribe(); }, [gfx, note]); const toggle = useCallback(() => { diff --git a/packages/frontend/core/src/components/hooks/use-all-block-suite-page-meta.ts b/packages/frontend/core/src/components/hooks/use-all-block-suite-page-meta.ts index e6b20ea6a0..9883b5dbaa 100644 --- a/packages/frontend/core/src/components/hooks/use-all-block-suite-page-meta.ts +++ b/packages/frontend/core/src/components/hooks/use-all-block-suite-page-meta.ts @@ -11,11 +11,11 @@ export function useAllBlockSuiteDocMeta(docCollection: Workspace): DocMeta[] { weakMap.set(docCollection, baseAtom); baseAtom.onMount = set => { set([...docCollection.meta.docMetas]); - const dispose = docCollection.slots.docListUpdated.on(() => { + const dispose = docCollection.slots.docListUpdated.subscribe(() => { set([...docCollection.meta.docMetas]); }); return () => { - dispose.dispose(); + dispose.unsubscribe(); }; }; } diff --git a/packages/frontend/core/src/components/hooks/use-block-suite-workspace-page.ts b/packages/frontend/core/src/components/hooks/use-block-suite-workspace-page.ts index 5713d504cf..94423f257a 100644 --- a/packages/frontend/core/src/components/hooks/use-block-suite-workspace-page.ts +++ b/packages/frontend/core/src/components/hooks/use-block-suite-workspace-page.ts @@ -1,5 +1,5 @@ import { DebugLogger } from '@affine/debug'; -import { DisposableGroup } from '@blocksuite/affine/global/slot'; +import { DisposableGroup } from '@blocksuite/affine/global/disposable'; import type { Store, Workspace } from '@blocksuite/affine/store'; import { useEffect, useState } from 'react'; @@ -16,14 +16,14 @@ export function useDocCollectionPage( useEffect(() => { const group = new DisposableGroup(); group.add( - docCollection.slots.docCreated.on(id => { + docCollection.slots.docCreated.subscribe(id => { if (pageId === id) { setPage(docCollection.getDoc(id)); } }) ); group.add( - docCollection.slots.docRemoved.on(id => { + docCollection.slots.docRemoved.subscribe(id => { if (pageId === id) { setPage(null); } diff --git a/packages/frontend/core/src/components/page-list/use-block-suite-page-preview.ts b/packages/frontend/core/src/components/page-list/use-block-suite-page-preview.ts index 02debbdcfa..2f6d3de2bc 100644 --- a/packages/frontend/core/src/components/page-list/use-block-suite-page-preview.ts +++ b/packages/frontend/core/src/components/page-list/use-block-suite-page-preview.ts @@ -69,16 +69,16 @@ export function useBlockSuitePagePreview(page: Store | null): Atom { const baseAtom = atom(''); baseAtom.onMount = set => { const disposables = [ - page.slots.ready.on(() => { + page.slots.ready.subscribe(() => { set(getPagePreviewText(page)); }), - page.slots.blockUpdated.on(() => { + page.slots.blockUpdated.subscribe(() => { set(getPagePreviewText(page)); }), ]; set(getPagePreviewText(page)); return () => { - disposables.forEach(disposable => disposable.dispose()); + disposables.forEach(disposable => disposable.unsubscribe()); }; }; weakMap.set(page, baseAtom); diff --git a/packages/frontend/core/src/components/page-list/use-block-suite-workspace-page.ts b/packages/frontend/core/src/components/page-list/use-block-suite-workspace-page.ts index aa23c32e4f..b84b43981f 100644 --- a/packages/frontend/core/src/components/page-list/use-block-suite-workspace-page.ts +++ b/packages/frontend/core/src/components/page-list/use-block-suite-workspace-page.ts @@ -1,5 +1,5 @@ import { DebugLogger } from '@affine/debug'; -import { DisposableGroup } from '@blocksuite/affine/global/slot'; +import { DisposableGroup } from '@blocksuite/affine/global/disposable'; import type { Store, Workspace } from '@blocksuite/affine/store'; import { useEffect, useState } from 'react'; @@ -16,14 +16,14 @@ export function useDocCollectionPage( useEffect(() => { const group = new DisposableGroup(); group.add( - docCollection.slots.docCreated.on(id => { + docCollection.slots.docCreated.subscribe(id => { if (pageId === id) { setPage(docCollection.getDoc(id)); } }) ); group.add( - docCollection.slots.docRemoved.on(id => { + docCollection.slots.docRemoved.subscribe(id => { if (pageId === id) { setPage(null); } diff --git a/packages/frontend/core/src/components/providers/workspace-side-effects.tsx b/packages/frontend/core/src/components/providers/workspace-side-effects.tsx index 997d9063b9..44b2827b8a 100644 --- a/packages/frontend/core/src/components/providers/workspace-side-effects.tsx +++ b/packages/frontend/core/src/components/providers/workspace-side-effects.tsx @@ -111,14 +111,14 @@ export const WorkspaceSideEffects = () => { }) ); - const disposable = AIProvider.slots.requestInsertTemplate.on( + const disposable = AIProvider.slots.requestInsertTemplate.subscribe( ({ template, mode }) => { insertTemplate({ template, mode }); } ); return () => { - disposable.dispose(); + disposable.unsubscribe(); insertTemplate.unsubscribe(); }; }, [ @@ -134,14 +134,14 @@ export const WorkspaceSideEffects = () => { const globalDialogService = useService(GlobalDialogService); useEffect(() => { - const disposable = AIProvider.slots.requestUpgradePlan.on(() => { + const disposable = AIProvider.slots.requestUpgradePlan.subscribe(() => { workspaceDialogService.open('setting', { activeTab: 'billing', }); track.$.paywall.aiAction.viewPlans(); }); return () => { - disposable.dispose(); + disposable.unsubscribe(); }; }, [workspaceDialogService]); diff --git a/packages/frontend/core/src/desktop/dialogs/setting/general-setting/editor/edgeless/snapshot.tsx b/packages/frontend/core/src/desktop/dialogs/setting/general-setting/editor/edgeless/snapshot.tsx index b5c7420719..0fe0bd878e 100644 --- a/packages/frontend/core/src/desktop/dialogs/setting/general-setting/editor/edgeless/snapshot.tsx +++ b/packages/frontend/core/src/desktop/dialogs/setting/general-setting/editor/edgeless/snapshot.tsx @@ -92,7 +92,7 @@ export const EdgelessSnapshot = (props: Props) => { // refresh viewport const gfx = editorHost.std.get(GfxControllerIdentifier); - const disposable = editorHost.std.view.viewUpdated.on(payload => { + const disposable = editorHost.std.view.viewUpdated.subscribe(payload => { if ( payload.type !== 'block' || payload.method !== 'add' || @@ -110,7 +110,7 @@ export const EdgelessSnapshot = (props: Props) => { const bound = boundMap.get(docName); bound && gfx.viewport.setViewportByBound(bound); doc.readonly = true; - disposable.dispose(); + disposable.unsubscribe(); }); // append to dom node diff --git a/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/preference/profile.tsx b/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/preference/profile.tsx index f84e69de41..64f656b348 100644 --- a/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/preference/profile.tsx +++ b/packages/frontend/core/src/desktop/dialogs/setting/workspace-setting/preference/profile.tsx @@ -42,13 +42,12 @@ export const ProfilePanel = () => { useEffect(() => { if (workspace?.docCollection) { setName(workspace.docCollection.meta.name ?? UNTITLED_WORKSPACE_NAME); - const dispose = workspace.docCollection.meta.commonFieldsUpdated.on( - () => { + const dispose = + workspace.docCollection.meta.commonFieldsUpdated.subscribe(() => { setName(workspace.docCollection.meta.name ?? UNTITLED_WORKSPACE_NAME); - } - ); + }); return () => { - dispose.dispose(); + dispose.unsubscribe(); }; } else { setName(UNTITLED_WORKSPACE_NAME); diff --git a/packages/frontend/core/src/desktop/pages/workspace/detail-page/detail-page.tsx b/packages/frontend/core/src/desktop/pages/workspace/detail-page/detail-page.tsx index ad1a3f6c33..568be593cf 100644 --- a/packages/frontend/core/src/desktop/pages/workspace/detail-page/detail-page.tsx +++ b/packages/frontend/core/src/desktop/pages/workspace/detail-page/detail-page.tsx @@ -18,10 +18,7 @@ import { ViewService } from '@affine/core/modules/workbench'; import { WorkspaceService } from '@affine/core/modules/workspace'; import { isNewTabTrigger } from '@affine/core/utils'; import track from '@affine/track'; -import { - type Disposable, - DisposableGroup, -} from '@blocksuite/affine/global/slot'; +import { DisposableGroup } from '@blocksuite/affine/global/disposable'; import { RefNodeSlotsProvider } from '@blocksuite/affine/rich-text'; import { AiIcon, @@ -39,6 +36,7 @@ import { import clsx from 'clsx'; import { memo, useCallback, useEffect, useRef, useState } from 'react'; import { useParams } from 'react-router-dom'; +import type { Subscription } from 'rxjs'; import { AffineErrorBoundary } from '../../../../components/affine/affine-error-boundary'; import { GlobalPageHistoryModal } from '../../../../components/affine/page-history-modal'; @@ -113,14 +111,18 @@ const DetailPageImpl = memo(function DetailPageImpl() { }, [editorContainer, isActiveView, setActiveBlockSuiteEditor]); useEffect(() => { - const disposables: Disposable[] = []; + const disposables: Subscription[] = []; const openHandler = () => { workbench.openSidebar(); view.activeSidebarTab('chat'); }; - 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()); }, [activeSidebarTab, view, workbench]); useEffect(() => { @@ -169,7 +171,7 @@ const DetailPageImpl = memo(function DetailPageImpl() { if (refNodeSlots) { disposable.add( // the event should not be emitted by AffineReference - refNodeSlots.docLinkClicked.on( + refNodeSlots.docLinkClicked.subscribe( ({ pageId, params, openMode, event, host }) => { if (host !== editorContainer.host) { return; diff --git a/packages/frontend/core/src/desktop/pages/workspace/detail-page/tabs/chat.tsx b/packages/frontend/core/src/desktop/pages/workspace/detail-page/tabs/chat.tsx index 390cc3f5da..0d14e37bd4 100644 --- a/packages/frontend/core/src/desktop/pages/workspace/detail-page/tabs/chat.tsx +++ b/packages/frontend/core/src/desktop/pages/workspace/detail-page/tabs/chat.tsx @@ -109,7 +109,7 @@ export const EditorChatPanel = forwardRef(function EditorChatPanel( const docModeService = editor.host.std.get(DocModeProvider); const refNodeService = editor.host.std.getOptional(RefNodeSlotsProvider); const disposable = [ - refNodeService?.docLinkClicked.on(({ host }) => { + refNodeService?.docLinkClicked.subscribe(({ host }) => { if (host === editor.host) { (chatPanelRef.current as ChatPanel).doc = editor.doc; } @@ -120,7 +120,7 @@ export const EditorChatPanel = forwardRef(function EditorChatPanel( }, editor.doc.id), ]; - return () => disposable.forEach(d => d?.dispose()); + return () => disposable.forEach(d => d?.unsubscribe()); }, [editor, framework]); return
; diff --git a/packages/frontend/core/src/desktop/pages/workspace/share/share-page.tsx b/packages/frontend/core/src/desktop/pages/workspace/share/share-page.tsx index 1c977fc607..c96bcb9160 100644 --- a/packages/frontend/core/src/desktop/pages/workspace/share/share-page.tsx +++ b/packages/frontend/core/src/desktop/pages/workspace/share/share-page.tsx @@ -20,7 +20,7 @@ import { WorkspacesService, } from '@affine/core/modules/workspace'; import { useI18n } from '@affine/i18n'; -import { DisposableGroup } from '@blocksuite/affine/global/slot'; +import { DisposableGroup } from '@blocksuite/affine/global/disposable'; import { type DocMode, DocModes } from '@blocksuite/affine/model'; import { RefNodeSlotsProvider } from '@blocksuite/affine/rich-text'; import { Logo1Icon } from '@blocksuite/icons/rc'; @@ -201,7 +201,7 @@ const SharePageInner = ({ editorContainer.host?.std.getOptional(RefNodeSlotsProvider); if (refNodeSlots) { disposable.add( - refNodeSlots.docLinkClicked.on(({ pageId, params }) => { + refNodeSlots.docLinkClicked.subscribe(({ pageId, params }) => { if (params) { const { mode, blockIds, elementIds } = params; jumpToPageBlock(workspaceId, pageId, mode, blockIds, elementIds); diff --git a/packages/frontend/core/src/mobile/pages/workspace/detail/mobile-detail-page.tsx b/packages/frontend/core/src/mobile/pages/workspace/detail/mobile-detail-page.tsx index a3f2ccf9ba..ae0389910c 100644 --- a/packages/frontend/core/src/mobile/pages/workspace/detail/mobile-detail-page.tsx +++ b/packages/frontend/core/src/mobile/pages/workspace/detail/mobile-detail-page.tsx @@ -25,7 +25,7 @@ import { customImageProxyMiddleware, ImageProxyService, } from '@blocksuite/affine/blocks/image'; -import { DisposableGroup } from '@blocksuite/affine/global/slot'; +import { DisposableGroup } from '@blocksuite/affine/global/disposable'; import { RefNodeSlotsProvider } from '@blocksuite/affine/rich-text'; import { LinkPreviewerService } from '@blocksuite/affine/shared/services'; import { @@ -162,7 +162,7 @@ const DetailPageImpl = () => { const disposable = new DisposableGroup(); if (refNodeService) { disposable.add( - refNodeService.docLinkClicked.on(({ pageId, params }) => { + refNodeService.docLinkClicked.subscribe(({ pageId, params }) => { if (params) { const { mode, blockIds, elementIds } = params; return jumpToPageBlock( diff --git a/packages/frontend/core/src/modules/cloud/services/auth.ts b/packages/frontend/core/src/modules/cloud/services/auth.ts index c752627c6f..9793b1fdf7 100644 --- a/packages/frontend/core/src/modules/cloud/services/auth.ts +++ b/packages/frontend/core/src/modules/cloud/services/auth.ts @@ -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); diff --git a/packages/frontend/core/src/modules/editor-setting/services/editor-setting.ts b/packages/frontend/core/src/modules/editor-setting/services/editor-setting.ts index a0ad7b0b0d..a8b219e021 100644 --- a/packages/frontend/core/src/modules/editor-setting/services/editor-setting.ts +++ b/packages/frontend/core/src/modules/editor-setting/services/editor-setting.ts @@ -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; diff --git a/packages/frontend/core/src/modules/editor/entities/editor.ts b/packages/frontend/core/src/modules/editor/entities/editor.ts index 0c64b96600..0e26a89111 100644 --- a/packages/frontend/core/src/modules/editor/entities/editor.ts +++ b/packages/frontend/core/src/modules/editor/entities/editor.ts @@ -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 diff --git a/packages/frontend/core/src/modules/peek-view/view/doc-preview/doc-peek-view.tsx b/packages/frontend/core/src/modules/peek-view/view/doc-preview/doc-peek-view.tsx index 1210136be6..25a86422a7 100644 --- a/packages/frontend/core/src/modules/peek-view/view/doc-preview/doc-peek-view.tsx +++ b/packages/frontend/core/src/modules/peek-view/view/doc-preview/doc-peek-view.tsx @@ -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 } }; - 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(() => { diff --git a/packages/frontend/core/src/modules/tag/stores/tag.ts b/packages/frontend/core/src/modules/tag/stores/tag.ts index 7a0f3d11c6..deff6726d6 100644 --- a/packages/frontend/core/src/modules/tag/stores/tag.ts +++ b/packages/frontend/core/src/modules/tag/stores/tag.ts @@ -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) { diff --git a/packages/frontend/core/src/modules/workspace/entities/workspace.ts b/packages/frontend/core/src/modules/workspace/entities/workspace.ts index bebad39be7..a99c19632f 100644 --- a/packages/frontend/core/src/modules/workspace/entities/workspace.ts +++ b/packages/frontend/core/src/modules/workspace/entities/workspace.ts @@ -73,9 +73,11 @@ export class Workspace extends Entity { name$ = LiveData.from( 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( 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 ); diff --git a/packages/frontend/core/src/modules/workspace/impls/doc.ts b/packages/frontend/core/src/modules/workspace/impls/doc.ts index 3059cd55cb..c9df4a553f 100644 --- a/packages/frontend/core/src/modules/workspace/impls/doc.ts +++ b/packages/frontend/core/src/modules/workspace/impls/doc.ts @@ -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(), + // 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>) { @@ -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); diff --git a/packages/frontend/core/src/modules/workspace/impls/meta.ts b/packages/frontend/core/src/modules/workspace/impls/meta.ts index fd0b48857d..683d31cba4 100644 --- a/packages/frontend/core/src/modules/workspace/impls/meta.ts +++ b/packages/frontend/core/src/modules/workspace/impls/meta.ts @@ -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(); - docMetaRemoved = new Slot(); - docMetaUpdated = new Slot(); + /* eslint-disable rxjs/finnish */ + commonFieldsUpdated = new Subject(); + docMetaAdded = new Subject(); + docMetaRemoved = new Subject(); + docMetaUpdated = new Subject(); + /* eslint-enable rxjs/finnish */ private readonly _handleDocCollectionMetaEvents = ( events: Y.YEvent | Y.Text | Y.Map>[] @@ -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) { diff --git a/packages/frontend/core/src/modules/workspace/impls/workspace.ts b/packages/frontend/core/src/modules/workspace/impls/workspace.ts index 44e285ca53..176e69d67a 100644 --- a/packages/frontend/core/src/modules/workspace/impls/workspace.ts +++ b/packages/frontend/core/src/modules/workspace/impls/workspace.ts @@ -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(), - docCreated: new Slot(), + /* eslint-disable rxjs/finnish */ + docListUpdated: new Subject(), + docRemoved: new Subject(), + docCreated: new Subject(), + /* 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, diff --git a/yarn.lock b/yarn.lock index bd6f4f6d69..e018da0057 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2230,6 +2230,7 @@ __metadata: file-type: "npm:^20.0.0" lit: "npm:^3.2.0" minimatch: "npm:^10.0.1" + rxjs: "npm:^7.8.1" zod: "npm:^3.23.8" languageName: unknown linkType: soft @@ -2253,6 +2254,7 @@ __metadata: "@toeverything/theme": "npm:^1.1.12" lit: "npm:^3.2.0" minimatch: "npm:^10.0.1" + rxjs: "npm:^7.8.1" yjs: "npm:^13.6.23" zod: "npm:^3.23.8" languageName: unknown @@ -2281,6 +2283,7 @@ __metadata: emoji-mart: "npm:^5.6.0" lit: "npm:^3.2.0" minimatch: "npm:^10.0.1" + rxjs: "npm:^7.8.1" zod: "npm:^3.23.8" languageName: unknown linkType: soft @@ -2306,6 +2309,7 @@ __metadata: "@types/mdast": "npm:^4.0.4" lit: "npm:^3.2.0" minimatch: "npm:^10.0.1" + rxjs: "npm:^7.8.1" shiki: "npm:^3.0.0" zod: "npm:^3.23.8" languageName: unknown @@ -2333,6 +2337,7 @@ __metadata: "@types/mdast": "npm:^4.0.4" lit: "npm:^3.2.0" minimatch: "npm:^10.0.1" + rxjs: "npm:^7.8.1" zod: "npm:^3.23.8" languageName: unknown linkType: soft @@ -2362,6 +2367,7 @@ __metadata: date-fns: "npm:^4.0.0" lit: "npm:^3.2.0" minimatch: "npm:^10.0.1" + rxjs: "npm:^7.8.1" yjs: "npm:^13.6.21" zod: "npm:^3.23.8" languageName: unknown @@ -2385,6 +2391,7 @@ __metadata: "@types/mdast": "npm:^4.0.4" lit: "npm:^3.2.0" minimatch: "npm:^10.0.1" + rxjs: "npm:^7.8.1" zod: "npm:^3.23.8" languageName: unknown linkType: soft @@ -2409,6 +2416,7 @@ __metadata: "@toeverything/theme": "npm:^1.1.12" lit: "npm:^3.2.0" minimatch: "npm:^10.0.1" + rxjs: "npm:^7.8.1" zod: "npm:^3.23.8" languageName: unknown linkType: soft @@ -2436,6 +2444,7 @@ __metadata: lit: "npm:^3.2.0" lodash-es: "npm:^4.17.21" minimatch: "npm:^10.0.1" + rxjs: "npm:^7.8.1" vitest: "npm:3.0.8" yjs: "npm:^13.6.21" zod: "npm:^3.23.8" @@ -2461,6 +2470,7 @@ __metadata: "@types/mdast": "npm:^4.0.4" lit: "npm:^3.2.0" minimatch: "npm:^10.0.1" + rxjs: "npm:^7.8.1" yjs: "npm:^13.6.21" zod: "npm:^3.23.8" languageName: unknown @@ -2488,6 +2498,7 @@ __metadata: file-type: "npm:^20.0.0" lit: "npm:^3.2.0" minimatch: "npm:^10.0.1" + rxjs: "npm:^7.8.1" zod: "npm:^3.23.8" languageName: unknown linkType: soft @@ -2517,6 +2528,7 @@ __metadata: lit: "npm:^3.2.0" minimatch: "npm:^10.0.1" remark-math: "npm:^6.0.0" + rxjs: "npm:^7.8.1" zod: "npm:^3.23.8" languageName: unknown linkType: soft @@ -2541,6 +2553,7 @@ __metadata: "@types/mdast": "npm:^4.0.4" lit: "npm:^3.2.0" minimatch: "npm:^10.0.1" + rxjs: "npm:^7.8.1" vitest: "npm:3.0.8" zod: "npm:^3.23.8" languageName: unknown @@ -2570,6 +2583,7 @@ __metadata: "@vanilla-extract/css": "npm:^1.17.0" lit: "npm:^3.2.0" minimatch: "npm:^10.0.1" + rxjs: "npm:^7.8.1" zod: "npm:^3.23.8" languageName: unknown linkType: soft @@ -2593,6 +2607,7 @@ __metadata: "@types/mdast": "npm:^4.0.4" lit: "npm:^3.2.0" minimatch: "npm:^10.0.1" + rxjs: "npm:^7.8.1" zod: "npm:^3.23.8" languageName: unknown linkType: soft @@ -2648,6 +2663,7 @@ __metadata: lit: "npm:^3.2.0" lodash-es: "npm:^4.17.21" minimatch: "npm:^10.0.1" + rxjs: "npm:^7.8.1" simple-xml-to-json: "npm:^1.2.2" yjs: "npm:^13.6.21" zod: "npm:^3.23.8" @@ -2676,6 +2692,7 @@ __metadata: lit: "npm:^3.2.0" lodash-es: "npm:^4.17.21" nanoid: "npm:^5.0.7" + rxjs: "npm:^7.8.1" zod: "npm:^3.23.8" languageName: unknown linkType: soft @@ -2702,6 +2719,7 @@ __metadata: lodash-es: "npm:^4.17.21" nanoid: "npm:^5.0.7" pdf-lib: "npm:^1.17.1" + rxjs: "npm:^7.8.1" vitest: "npm:3.0.8" yjs: "npm:^13.6.21" zod: "npm:^3.23.8" @@ -2727,6 +2745,7 @@ __metadata: "@preact/signals-core": "npm:^1.8.0" "@vanilla-extract/css": "npm:^1.17.0" lit: "npm:^3.2.0" + rxjs: "npm:^7.8.1" yjs: "npm:^13.6.21" zod: "npm:^3.24.1" languageName: unknown @@ -2759,6 +2778,7 @@ __metadata: lit-html: "npm:^3.2.1" lodash-es: "npm:^4.17.21" remark-math: "npm:^6.0.0" + rxjs: "npm:^7.8.1" shiki: "npm:^3.0.0" yjs: "npm:^13.6.21" zod: "npm:^3.23.8" @@ -2786,6 +2806,7 @@ __metadata: "@toeverything/theme": "npm:^1.1.12" lit: "npm:^3.2.0" minimatch: "npm:^10.0.1" + rxjs: "npm:^7.8.1" zod: "npm:^3.23.8" languageName: unknown linkType: soft @@ -2813,6 +2834,7 @@ __metadata: lit: "npm:^3.2.0" lodash-es: "npm:^4.17.21" minimatch: "npm:^10.0.1" + rxjs: "npm:^7.8.1" zod: "npm:^3.23.8" languageName: unknown linkType: soft @@ -2839,6 +2861,7 @@ __metadata: "@vanilla-extract/css": "npm:^1.17.0" lit: "npm:^3.2.0" minimatch: "npm:^10.0.1" + rxjs: "npm:^7.8.1" zod: "npm:^3.23.8" languageName: unknown linkType: soft @@ -2865,6 +2888,7 @@ __metadata: lit: "npm:^3.2.0" lodash-es: "npm:^4.17.21" minimatch: "npm:^10.0.1" + rxjs: "npm:^7.8.1" yjs: "npm:^13.6.21" zod: "npm:^3.23.8" languageName: unknown @@ -2878,6 +2902,7 @@ __metadata: "@blocksuite/global": "workspace:*" "@types/lodash-es": "npm:^4.17.12" lodash-es: "npm:^4.17.21" + rxjs: "npm:^7.8.1" tweakpane: "npm:^4.0.5" languageName: unknown linkType: soft @@ -2894,6 +2919,7 @@ __metadata: "@types/lodash-es": "npm:^4.17.12" fractional-indexing: "npm:^3.2.0" lodash-es: "npm:^4.17.21" + rxjs: "npm:^7.8.1" yjs: "npm:^13.6.21" zod: "npm:^3.23.8" languageName: unknown @@ -2927,6 +2953,7 @@ __metadata: lit-html: "npm:^3.2.1" lodash-es: "npm:^4.17.21" remark-math: "npm:^6.0.0" + rxjs: "npm:^7.8.1" shiki: "npm:^3.0.0" yjs: "npm:^13.6.21" zod: "npm:^3.23.8" @@ -2971,6 +2998,7 @@ __metadata: remark-math: "npm:^6.0.0" remark-parse: "npm:^11.0.0" remark-stringify: "npm:^11.0.0" + rxjs: "npm:^7.8.1" unified: "npm:^11.0.5" vitest: "npm:3.0.8" yjs: "npm:^13.6.21" @@ -3003,6 +3031,7 @@ __metadata: lit: "npm:^3.2.0" lodash-es: "npm:^4.17.21" minimatch: "npm:^10.0.1" + rxjs: "npm:^7.8.1" zod: "npm:^3.23.8" languageName: unknown linkType: soft @@ -3022,6 +3051,7 @@ __metadata: "@preact/signals-core": "npm:^1.8.0" "@toeverything/theme": "npm:^1.1.12" lit: "npm:^3.2.0" + rxjs: "npm:^7.8.1" languageName: unknown linkType: soft @@ -3038,6 +3068,7 @@ __metadata: "@preact/signals-core": "npm:^1.8.0" "@toeverything/theme": "npm:^1.1.12" lit: "npm:^3.2.0" + rxjs: "npm:^7.8.1" languageName: unknown linkType: soft @@ -3057,6 +3088,7 @@ __metadata: "@types/lodash-es": "npm:^4.17.12" lit: "npm:^3.2.0" lodash-es: "npm:^4.17.21" + rxjs: "npm:^7.8.1" languageName: unknown linkType: soft @@ -3071,6 +3103,7 @@ __metadata: "@preact/signals-core": "npm:^1.8.0" "@toeverything/theme": "npm:^1.1.12" lit: "npm:^3.2.0" + rxjs: "npm:^7.8.1" languageName: unknown linkType: soft @@ -3092,6 +3125,7 @@ __metadata: "@types/lodash-es": "npm:^4.17.12" lit: "npm:^3.2.0" lodash-es: "npm:^4.17.21" + rxjs: "npm:^7.8.1" languageName: unknown linkType: soft @@ -3118,6 +3152,7 @@ __metadata: "@types/lodash.topairs": "npm:^4" lit: "npm:^3.2.0" lodash-es: "npm:^4.17.21" + rxjs: "npm:^7.8.1" languageName: unknown linkType: soft @@ -3167,6 +3202,7 @@ __metadata: "@blocksuite/store": "workspace:*" "@blocksuite/sync": "workspace:*" "@vanilla-extract/vite-plugin": "npm:^5.0.0" + rxjs: "npm:^7.8.1" vitest: "npm:3.0.8" languageName: unknown linkType: soft @@ -3192,6 +3228,7 @@ __metadata: lodash-es: "npm:^4.17.21" lz-string: "npm:^1.5.0" rehype-parse: "npm:^9.0.0" + rxjs: "npm:^7.8.1" unified: "npm:^11.0.5" vitest: "npm:3.0.8" w3c-keyname: "npm:^2.2.8" @@ -3220,6 +3257,7 @@ __metadata: date-fns: "npm:^4.0.0" lit: "npm:^3.2.0" lodash-es: "npm:^4.17.21" + rxjs: "npm:^7.8.1" yjs: "npm:^13.6.21" zod: "npm:^3.23.8" languageName: unknown @@ -3232,6 +3270,7 @@ __metadata: "@preact/signals-core": "npm:^1.8.0" lib0: "npm:^0.2.97" lit: "npm:^3.2.0" + rxjs: "npm:^7.8.1" vitest: "npm:3.0.8" zod: "npm:^3.23.8" languageName: unknown @@ -3261,6 +3300,7 @@ __metadata: "@blocksuite/global": "workspace:*" "@preact/signals-core": "npm:^1.8.0" lit: "npm:^3.2.0" + rxjs: "npm:^7.8.1" vitest: "npm:3.0.8" yjs: "npm:^13.6.21" zod: "npm:^3.23.8" @@ -3281,6 +3321,7 @@ __metadata: "@vanilla-extract/css": "npm:^1.17.0" "@vanilla-extract/vite-plugin": "npm:^5.0.0" lit: "npm:^3.2.0" + rxjs: "npm:^7.8.1" vite: "npm:^6.1.0" vite-plugin-istanbul: "npm:^7.0.0" vite-plugin-wasm: "npm:^3.4.1" @@ -3298,6 +3339,7 @@ __metadata: "@blocksuite/integration-test": "workspace:*" "@playwright/test": "npm:=1.51.0" "@toeverything/theme": "npm:^1.1.12" + rxjs: "npm:^7.8.1" languageName: unknown linkType: soft @@ -3327,6 +3369,7 @@ __metadata: lit: "npm:^3.2.0" lz-string: "npm:^1.5.0" magic-string: "npm:^0.30.11" + rxjs: "npm:^7.8.1" tweakpane: "npm:^4.0.4" vite: "npm:^6.0.3" vite-plugin-istanbul: "npm:^7.0.0" @@ -3357,6 +3400,7 @@ __metadata: lodash.merge: "npm:^4.6.2" minimatch: "npm:^10.0.1" nanoid: "npm:^5.0.7" + rxjs: "npm:^7.8.1" vitest: "npm:3.0.8" y-protocols: "npm:^1.0.6" yjs: "npm:^13.6.21" @@ -3373,6 +3417,7 @@ __metadata: idb: "npm:^8.0.0" idb-keyval: "npm:^6.2.1" lodash-es: "npm:^4.17.21" + rxjs: "npm:^7.8.1" vitest: "npm:3.0.8" y-protocols: "npm:^1.0.6" peerDependencies: