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

This commit is contained in:
Mirone
2025-03-12 11:29:24 +09:00
committed by GitHub
parent 19f978d9aa
commit cd63e0ed8b
302 changed files with 1405 additions and 1251 deletions
@@ -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<boolean>;
navigatorSettingUpdated: Slot<{
readonlyUpdated: Subject<boolean>;
navigatorSettingUpdated: Subject<{
hideToolbar?: boolean;
blackBackground?: boolean;
fillScreen?: boolean;
}>;
navigatorFrameChanged: Slot<FrameBlockModel>;
fullScreenToggled: Slot;
navigatorFrameChanged: Subject<FrameBlockModel>;
fullScreenToggled: Subject<void>;
elementResizeStart: Slot;
elementResizeEnd: Slot;
toggleNoteSlicer: Slot;
elementResizeStart: Subject<void>;
elementResizeEnd: Subject<void>;
toggleNoteSlicer: Subject<void>;
toolbarLocked: Slot<boolean>;
toolbarLocked: Subject<boolean>;
}>('AffineEdgelessLegacySlotService');
export const EdgelessLegacySlotExtension: ExtensionType = {
setup: di => {
di.addImpl(EdgelessLegacySlotIdentifier, () => ({
readonlyUpdated: new Slot<boolean>(),
navigatorSettingUpdated: new Slot<{
readonlyUpdated: new Subject<boolean>(),
navigatorSettingUpdated: new Subject<{
hideToolbar?: boolean;
blackBackground?: boolean;
fillScreen?: boolean;
}>(),
navigatorFrameChanged: new Slot<FrameBlockModel>(),
fullScreenToggled: new Slot(),
elementResizeStart: new Slot(),
elementResizeEnd: new Slot(),
toggleNoteSlicer: new Slot(),
toolbarLocked: new Slot<boolean>(),
navigatorFrameChanged: new Subject<FrameBlockModel>(),
fullScreenToggled: new Subject(),
elementResizeStart: new Subject(),
elementResizeEnd: new Subject(),
toggleNoteSlicer: new Subject(),
toolbarLocked: new Subject<boolean>(),
}));
},
};
@@ -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<EnvProvider>;
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();
@@ -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<SurfaceSelection[]>;
updated: Subject<SurfaceSelection[]>;
};
};
}
@@ -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();
})
);
@@ -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';
@@ -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;
@@ -61,7 +61,7 @@ export class MindMapView extends GfxElementModelView<MindmapElementModel> {
});
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<MindmapElementModel> {
);
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<MindmapElementModel> {
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) {
@@ -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());
};
};
@@ -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());
};
};