mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 20:38:52 +00:00
feat(editor): replace slot with rxjs subject (#10768)
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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<void>(),
|
||||
mounted: new Subject<void>(),
|
||||
rendered: new Subject<void>(),
|
||||
unmounted: new Subject<void>(),
|
||||
};
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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);
|
||||
})
|
||||
);
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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);
|
||||
})
|
||||
);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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<keyof Props | string, unknown>;
|
||||
|
||||
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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<SurfaceBlockProps> {
|
||||
|
||||
protected _surfaceBlockModel = true;
|
||||
|
||||
elementAdded = new Slot<{ id: string; local: boolean }>();
|
||||
protected localElements = new Set<GfxLocalElementModel>();
|
||||
|
||||
elementRemoved = new Slot<{
|
||||
elementAdded = new Subject<{ id: string; local: boolean }>();
|
||||
|
||||
elementRemoved = new Subject<{
|
||||
id: string;
|
||||
type: string;
|
||||
model: GfxPrimitiveElementModel;
|
||||
local: boolean;
|
||||
}>();
|
||||
|
||||
elementUpdated = new Slot<ElementUpdatedData>();
|
||||
elementUpdated = new Subject<ElementUpdatedData>();
|
||||
|
||||
localElementAdded = new Slot<GfxLocalElementModel>();
|
||||
localElementAdded = new Subject<GfxLocalElementModel>();
|
||||
|
||||
localElementDeleted = new Slot<GfxLocalElementModel>();
|
||||
localElementDeleted = new Subject<GfxLocalElementModel>();
|
||||
|
||||
protected localElements = new Set<GfxLocalElementModel>();
|
||||
|
||||
localElementUpdated = new Slot<{
|
||||
localElementUpdated = new Subject<{
|
||||
model: GfxLocalElementModel;
|
||||
props: Record<string, unknown>;
|
||||
oldValues: Record<string, unknown>;
|
||||
@@ -122,7 +123,10 @@ export class SurfaceBlockModel extends BlockModel<SurfaceBlockProps> {
|
||||
|
||||
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<SurfaceBlockProps> {
|
||||
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<SurfaceBlockProps> {
|
||||
|
||||
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<SurfaceBlockProps> {
|
||||
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<SurfaceBlockProps> {
|
||||
|
||||
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<SurfaceBlockProps> {
|
||||
}
|
||||
});
|
||||
|
||||
this.deleted.on(() => {
|
||||
this.deleted.subscribe(() => {
|
||||
elementsYMap.unobserve(onElementsMapChange);
|
||||
disposable.dispose();
|
||||
subscription.unsubscribe();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -435,7 +439,7 @@ export class SurfaceBlockModel extends BlockModel<SurfaceBlockProps> {
|
||||
): 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<SurfaceBlockProps> {
|
||||
this.deleteElement(id);
|
||||
}
|
||||
});
|
||||
this.deleted.on(() => {
|
||||
disposable.dispose();
|
||||
this.deleted.subscribe(() => {
|
||||
disposable.unsubscribe();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -458,14 +462,14 @@ export class SurfaceBlockModel extends BlockModel<SurfaceBlockProps> {
|
||||
};
|
||||
|
||||
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<SurfaceBlockProps> {
|
||||
|
||||
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<SurfaceBlockProps> {
|
||||
|
||||
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<SurfaceBlockProps> {
|
||||
|
||||
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();
|
||||
|
||||
@@ -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<SurfaceSelection[]>(),
|
||||
remoteUpdated: new Slot(),
|
||||
updated: new Subject<SurfaceSelection[]>(),
|
||||
remoteUpdated: new Subject<void>(),
|
||||
|
||||
cursorUpdated: new Slot<CursorSelection>(),
|
||||
remoteCursorUpdated: new Slot(),
|
||||
cursorUpdated: new Subject<CursorSelection>(),
|
||||
remoteCursorUpdated: new Subject<void>(),
|
||||
};
|
||||
|
||||
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<number, SurfaceSelection[]>();
|
||||
const cursorMap = new Map<number, CursorSelection>();
|
||||
const selectedSet = new Set<string>();
|
||||
@@ -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();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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<BuiltInSlotContext>();
|
||||
private readonly _builtInHookSlot = new Subject<BuiltInSlotContext>();
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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<GfxViewportElement>();
|
||||
elementReady = new Subject<GfxViewportElement>();
|
||||
|
||||
sizeUpdated = new Slot<{
|
||||
sizeUpdated = new Subject<{
|
||||
width: number;
|
||||
height: number;
|
||||
left: number;
|
||||
top: number;
|
||||
}>();
|
||||
|
||||
viewportMoved = new Slot<IVec>();
|
||||
viewportMoved = new Subject<IVec>();
|
||||
|
||||
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,
|
||||
});
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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<Service extends BlockService = BlockService> = {
|
||||
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<Service extends BlockService = BlockService> = {
|
||||
|
||||
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(),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
@@ -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<string, BlockComponent>();
|
||||
|
||||
viewUpdated: Slot<ViewUpdatePayload> = new Slot();
|
||||
viewUpdated: Subject<ViewUpdatePayload> = 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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user