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
@@ -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';
@@ -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';
@@ -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,
@@ -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()
)
);
@@ -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;
})
@@ -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();
@@ -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();
}
@@ -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<ShapeTool['activatedOption']['shapeName']>(),
select: new Subject<ShapeTool['activatedOption']['shapeName']>(),
};
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();
}
@@ -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<void>(),
dragMove: new Subject<void>(),
dragRotate: new Subject<void>(),
dragEnd: new Subject<void>(),
};
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(
@@ -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();
})
);
@@ -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();
})
);
@@ -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();
})
);
@@ -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();
})
);
@@ -386,7 +386,7 @@ export class EdgelessDraggableElementController<T>
hostConnected() {
this.host.disposables.add(
this.options.service.viewport.viewportUpdated.on(({ zoom }) => {
this.options.service.viewport.viewportUpdated.subscribe(({ zoom }) => {
this._updateOverlayScale(zoom);
})
);
@@ -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())
);
}
@@ -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<EdgelessToolbarSlots>(
@@ -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();
}
@@ -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';
@@ -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) {
<div class="text">Black background</div>
<toggle-switch
.on=${this.blackBackground}
.subscribe=${this.blackBackground}
.onChange=${this._onBlackBackgroundChange}
>
</toggle-switch>
@@ -144,7 +144,7 @@ export class EdgelessNavigatorSettingButton extends WithDisposable(LitElement) {
<div class="text">Hide toolbar</div>
<toggle-switch
.on=${this.hideToolbar}
.subscribe=${this.hideToolbar}
.onChange=${(checked: boolean) => {
this.onHideToolbarChange && this.onHideToolbarChange(checked);
}}
@@ -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 =
@@ -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';
@@ -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();
}
},
'@': () => {
@@ -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();
})
);
@@ -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();
})
);
@@ -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);
}
})
);
@@ -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() &&
@@ -69,7 +69,7 @@ export class NoteTool extends BaseTool<NoteToolOption> {
endY = startY + (endY > startY ? m : -m);
}
_draggingNoteOverlay.slots.draggingNoteUpdated.emit({
_draggingNoteOverlay.slots.draggingNoteUpdated.next({
xywh: [
Math.min(startX, endX),
Math.min(startY, endY),
@@ -9,7 +9,7 @@ import type { SlotBlockPayload, TemplateJob } from './template.js';
export const replaceIdMiddleware = (job: TemplateJob) => {
const regeneratedIdMap = new Map<string, string>();
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();
}
@@ -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,
@@ -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();
})
@@ -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();
}
@@ -42,13 +42,13 @@ export class EdgelessNavigatorBlackBackgroundWidget extends WidgetComponent<Root
override firstUpdated() {
const { _disposables, gfx } = this;
_disposables.add(
this._slots.navigatorFrameChanged.on(frame => {
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<Root
);
_disposables.add(
this._slots.fullScreenToggled.on(
this._slots.fullScreenToggled.subscribe(
() =>
setTimeout(() => {
this.requestUpdate();
@@ -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;
}
@@ -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();
})
);
@@ -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();
})
);
@@ -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()
)
);
@@ -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();
@@ -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, {
@@ -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
@@ -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();
},
@@ -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';
@@ -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;
@@ -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();
}
@@ -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);