refactor(editor): remove legacy service watcher (#10455)
The main changes in this PR involve replacing the deprecated `BlockServiceWatcher` with the new `LifeCycleWatcher` across multiple files. Here's a detailed breakdown:
1. **Core Architectural Change:**
- Removed `BlockServiceWatcher` class completely (deleted file)
- Migrated to `LifeCycleWatcher` as the new standard for watching component lifecycle events
2. **Key Changes in Implementation:**
- Changed from using `blockService.specSlots` events to using `view.viewUpdated` events
- Replaced `flavour` static property with `key` static property
- Updated event handling to use more specific payload type checking
3. **Major File Changes:**
- Modified multiple block components:
- Embed synced doc block
- Frame preview
- Edgeless root spec
- AI-related components (code, image, paragraph, etc.)
- Quick search service
- Edgeless clipboard
4. **Pattern of Changes:**
The migration follows a consistent pattern:
```typescript
// Old pattern
class SomeWatcher extends BlockServiceWatcher {
static override readonly flavour = 'some:flavour';
mounted() {
this.blockService.specSlots.viewConnected.on(...)
}
}
// New pattern
class SomeWatcher extends LifeCycleWatcher {
static override key = 'some-watcher';
mounted() {
const { view } = this.std;
view.viewUpdated.on(payload => {
if (payload.type !== 'block' || payload.method !== 'add') return;
// Handle event
});
}
}
```
5. **Benefits:**
- More explicit and type-safe event handling
- Cleaner architecture by removing deprecated code
- More consistent approach to lifecycle management
- Better separation of concerns
This appears to be a significant architectural improvement that modernizes the codebase by removing deprecated patterns and standardizing on a more robust lifecycle management system.
This commit is contained in:
@@ -26,9 +26,9 @@ import {
|
|||||||
} from '@blocksuite/affine-shared/utils';
|
} from '@blocksuite/affine-shared/utils';
|
||||||
import {
|
import {
|
||||||
BlockSelection,
|
BlockSelection,
|
||||||
BlockServiceWatcher,
|
|
||||||
BlockStdScope,
|
BlockStdScope,
|
||||||
type EditorHost,
|
type EditorHost,
|
||||||
|
LifeCycleWatcher,
|
||||||
} from '@blocksuite/block-std';
|
} from '@blocksuite/block-std';
|
||||||
import {
|
import {
|
||||||
GfxControllerIdentifier,
|
GfxControllerIdentifier,
|
||||||
@@ -124,27 +124,31 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent<EmbedSynce
|
|||||||
this.std.getOptional(EditorSettingProvider) ??
|
this.std.getOptional(EditorSettingProvider) ??
|
||||||
signal(GeneralSettingSchema.parse({}));
|
signal(GeneralSettingSchema.parse({}));
|
||||||
|
|
||||||
class EmbedSyncedDocWatcher extends BlockServiceWatcher {
|
class EmbedSyncedDocWatcher extends LifeCycleWatcher {
|
||||||
static override readonly flavour = 'affine:embed-synced-doc';
|
static override key = 'embed-synced-doc-watcher';
|
||||||
|
|
||||||
override mounted() {
|
override mounted(): void {
|
||||||
const disposableGroup = this.blockService.disposables;
|
const { view } = this.std;
|
||||||
const slots = this.blockService.specSlots;
|
view.viewUpdated.on(payload => {
|
||||||
disposableGroup.add(
|
if (
|
||||||
slots.viewConnected.on(({ component }) => {
|
payload.type !== 'block' ||
|
||||||
const nextComponent = component as EmbedSyncedDocBlockComponent;
|
payload.view.model.flavour !== 'affine:embed-synced-doc'
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const nextComponent = payload.view as EmbedSyncedDocBlockComponent;
|
||||||
|
if (payload.method === 'add') {
|
||||||
nextComponent.depth = nextDepth;
|
nextComponent.depth = nextDepth;
|
||||||
currentDisposables.add(() => {
|
currentDisposables.add(() => {
|
||||||
nextComponent.depth = 0;
|
nextComponent.depth = 0;
|
||||||
});
|
});
|
||||||
})
|
return;
|
||||||
);
|
}
|
||||||
disposableGroup.add(
|
if (payload.method === 'delete') {
|
||||||
slots.viewDisconnected.on(({ component }) => {
|
|
||||||
const nextComponent = component as EmbedSyncedDocBlockComponent;
|
|
||||||
nextComponent.depth = 0;
|
nextComponent.depth = 0;
|
||||||
})
|
return;
|
||||||
);
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import type { FrameBlockModel } from '@blocksuite/affine-model';
|
import type { FrameBlockModel } from '@blocksuite/affine-model';
|
||||||
import { SpecProvider } from '@blocksuite/affine-shared/utils';
|
import { SpecProvider } from '@blocksuite/affine-shared/utils';
|
||||||
import {
|
import {
|
||||||
BlockServiceWatcher,
|
|
||||||
BlockStdScope,
|
BlockStdScope,
|
||||||
type EditorHost,
|
type EditorHost,
|
||||||
|
LifeCycleWatcher,
|
||||||
ShadowlessElement,
|
ShadowlessElement,
|
||||||
} from '@blocksuite/block-std';
|
} from '@blocksuite/block-std';
|
||||||
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
|
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
|
||||||
@@ -117,22 +117,26 @@ export class FramePreview extends WithDisposable(ShadowlessElement) {
|
|||||||
|
|
||||||
private _initSpec() {
|
private _initSpec() {
|
||||||
const refreshViewport = this._refreshViewport.bind(this);
|
const refreshViewport = this._refreshViewport.bind(this);
|
||||||
class FramePreviewWatcher extends BlockServiceWatcher {
|
class FramePreviewWatcher extends LifeCycleWatcher {
|
||||||
static override readonly flavour = 'affine:page';
|
static override key = 'frame-preview-watcher';
|
||||||
|
|
||||||
override mounted() {
|
override mounted() {
|
||||||
const blockService = this.blockService;
|
const { view } = this.std;
|
||||||
blockService.disposables.add(
|
view.viewUpdated.on(payload => {
|
||||||
blockService.specSlots.viewConnected.on(({ component }) => {
|
if (
|
||||||
|
payload.type !== 'block' ||
|
||||||
|
payload.method !== 'add' ||
|
||||||
|
payload.view.model.flavour !== 'affine:page'
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const edgelessBlock =
|
const edgelessBlock =
|
||||||
component as EdgelessRootPreviewBlockComponent;
|
payload.view as EdgelessRootPreviewBlockComponent;
|
||||||
|
|
||||||
edgelessBlock.editorViewportSelector = 'frame-preview-viewport';
|
edgelessBlock.editorViewportSelector = 'frame-preview-viewport';
|
||||||
edgelessBlock.service.viewport.sizeUpdated.once(() => {
|
edgelessBlock.service.viewport.sizeUpdated.once(() => {
|
||||||
refreshViewport();
|
refreshViewport();
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this._previewSpec.extend([FramePreviewWatcher]);
|
this._previewSpec.extend([FramePreviewWatcher]);
|
||||||
|
|||||||
@@ -2,11 +2,14 @@ import { autoConnectWidget } from '@blocksuite/affine-widget-edgeless-auto-conne
|
|||||||
import { frameTitleWidget } from '@blocksuite/affine-widget-frame-title';
|
import { frameTitleWidget } from '@blocksuite/affine-widget-frame-title';
|
||||||
import { edgelessRemoteSelectionWidget } from '@blocksuite/affine-widget-remote-selection';
|
import { edgelessRemoteSelectionWidget } from '@blocksuite/affine-widget-remote-selection';
|
||||||
import {
|
import {
|
||||||
BlockServiceWatcher,
|
|
||||||
BlockViewExtension,
|
BlockViewExtension,
|
||||||
|
LifeCycleWatcher,
|
||||||
WidgetViewExtension,
|
WidgetViewExtension,
|
||||||
} from '@blocksuite/block-std';
|
} from '@blocksuite/block-std';
|
||||||
import { ToolController } from '@blocksuite/block-std/gfx';
|
import {
|
||||||
|
GfxControllerIdentifier,
|
||||||
|
ToolController,
|
||||||
|
} from '@blocksuite/block-std/gfx';
|
||||||
import type { ExtensionType } from '@blocksuite/store';
|
import type { ExtensionType } from '@blocksuite/store';
|
||||||
import { literal, unsafeStatic } from 'lit/static-html.js';
|
import { literal, unsafeStatic } from 'lit/static-html.js';
|
||||||
|
|
||||||
@@ -56,17 +59,12 @@ export const edgelessToolbarWidget = WidgetViewExtension(
|
|||||||
literal`${unsafeStatic(EDGELESS_TOOLBAR_WIDGET)}`
|
literal`${unsafeStatic(EDGELESS_TOOLBAR_WIDGET)}`
|
||||||
);
|
);
|
||||||
|
|
||||||
class EdgelessLocker extends BlockServiceWatcher {
|
class EdgelessLocker extends LifeCycleWatcher {
|
||||||
static override readonly flavour = 'affine:page';
|
static override key = 'edgeless-locker';
|
||||||
|
|
||||||
override mounted() {
|
override mounted() {
|
||||||
const service = this.blockService;
|
const { viewport } = this.std.get(GfxControllerIdentifier);
|
||||||
service.disposables.add(
|
viewport.locked = true;
|
||||||
service.specSlots.viewConnected.on(({ service }) => {
|
|
||||||
// Does not allow the user to move and zoom.
|
|
||||||
(service as EdgelessRootService).locked = true;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,5 +5,4 @@ export * from './flavour.js';
|
|||||||
export * from './keymap.js';
|
export * from './keymap.js';
|
||||||
export * from './lifecycle-watcher.js';
|
export * from './lifecycle-watcher.js';
|
||||||
export * from './service.js';
|
export * from './service.js';
|
||||||
export * from './service-watcher.js';
|
|
||||||
export * from './widget-view-map.js';
|
export * from './widget-view-map.js';
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
import type { Container } from '@blocksuite/global/di';
|
|
||||||
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
|
|
||||||
|
|
||||||
import {
|
|
||||||
BlockServiceIdentifier,
|
|
||||||
LifeCycleWatcherIdentifier,
|
|
||||||
StdIdentifier,
|
|
||||||
} from '../identifier.js';
|
|
||||||
import type { BlockStdScope } from '../scope/index.js';
|
|
||||||
import { LifeCycleWatcher } from './lifecycle-watcher.js';
|
|
||||||
import type { BlockService } from './service.js';
|
|
||||||
|
|
||||||
const idMap = new Map<string, number>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
* BlockServiceWatcher is deprecated. You should reconsider where to put your feature.
|
|
||||||
*
|
|
||||||
* BlockServiceWatcher is a legacy extension that is used to watch the slots registered on block service.
|
|
||||||
* However, we recommend using the new extension system.
|
|
||||||
*/
|
|
||||||
export abstract class BlockServiceWatcher extends LifeCycleWatcher {
|
|
||||||
static flavour: string;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
std: BlockStdScope,
|
|
||||||
readonly blockService: BlockService
|
|
||||||
) {
|
|
||||||
super(std);
|
|
||||||
}
|
|
||||||
|
|
||||||
static override setup(di: Container) {
|
|
||||||
if (!this.flavour) {
|
|
||||||
throw new BlockSuiteError(
|
|
||||||
ErrorCode.ValueNotExists,
|
|
||||||
'Flavour is not defined in the BlockServiceWatcher'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const id = idMap.get(this.flavour) ?? 0;
|
|
||||||
idMap.set(this.flavour, id + 1);
|
|
||||||
di.addImpl(
|
|
||||||
LifeCycleWatcherIdentifier(`${this.flavour}-watcher-${id}`),
|
|
||||||
this,
|
|
||||||
[StdIdentifier, BlockServiceIdentifier(this.flavour)]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { BlockServiceWatcher } from '@blocksuite/affine/block-std';
|
import { LifeCycleWatcher } from '@blocksuite/affine/block-std';
|
||||||
import {
|
import {
|
||||||
AffineCodeToolbarWidget,
|
AffineCodeToolbarWidget,
|
||||||
CodeBlockSpec,
|
CodeBlockSpec,
|
||||||
@@ -7,15 +7,19 @@ import type { ExtensionType } from '@blocksuite/affine/store';
|
|||||||
|
|
||||||
import { setupCodeToolbarAIEntry } from '../entries/code-toolbar/setup-code-toolbar';
|
import { setupCodeToolbarAIEntry } from '../entries/code-toolbar/setup-code-toolbar';
|
||||||
|
|
||||||
class AICodeBlockWatcher extends BlockServiceWatcher {
|
class AICodeBlockWatcher extends LifeCycleWatcher {
|
||||||
static override readonly flavour = 'affine:code';
|
static override key = 'ai-code-block-watcher';
|
||||||
|
|
||||||
override mounted() {
|
override mounted() {
|
||||||
super.mounted();
|
super.mounted();
|
||||||
const service = this.blockService;
|
const { view } = this.std;
|
||||||
service.specSlots.widgetConnected.on(view => {
|
view.viewUpdated.on(payload => {
|
||||||
if (view.component instanceof AffineCodeToolbarWidget) {
|
if (payload.type !== 'widget' || payload.method !== 'add') {
|
||||||
setupCodeToolbarAIEntry(view.component);
|
return;
|
||||||
|
}
|
||||||
|
const component = payload.view;
|
||||||
|
if (component instanceof AffineCodeToolbarWidget) {
|
||||||
|
setupCodeToolbarAIEntry(component);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { BlockServiceWatcher } from '@blocksuite/affine/block-std';
|
import { LifeCycleWatcher } from '@blocksuite/affine/block-std';
|
||||||
import {
|
import {
|
||||||
AffineFormatBarWidget,
|
AffineFormatBarWidget,
|
||||||
AffineSlashMenuWidget,
|
AffineSlashMenuWidget,
|
||||||
@@ -39,32 +39,37 @@ export function createAIEdgelessRootBlockSpec(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getAIEdgelessRootWatcher(framework: FrameworkProvider) {
|
function getAIEdgelessRootWatcher(framework: FrameworkProvider) {
|
||||||
class AIEdgelessRootWatcher extends BlockServiceWatcher {
|
class AIEdgelessRootWatcher extends LifeCycleWatcher {
|
||||||
static override readonly flavour = 'affine:page';
|
static override key = 'ai-edgeless-root-watcher';
|
||||||
|
|
||||||
override mounted() {
|
override mounted() {
|
||||||
super.mounted();
|
super.mounted();
|
||||||
this.blockService.specSlots.widgetConnected.on(view => {
|
const { view } = this.std;
|
||||||
if (view.component instanceof AffineAIPanelWidget) {
|
view.viewUpdated.on(payload => {
|
||||||
view.component.style.width = '430px';
|
if (payload.type !== 'widget' || payload.method !== 'add') {
|
||||||
view.component.config = buildAIPanelConfig(view.component, framework);
|
return;
|
||||||
setupSpaceAIEntry(view.component);
|
}
|
||||||
|
const component = payload.view;
|
||||||
|
if (component instanceof AffineAIPanelWidget) {
|
||||||
|
component.style.width = '430px';
|
||||||
|
component.config = buildAIPanelConfig(component, framework);
|
||||||
|
setupSpaceAIEntry(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (view.component instanceof EdgelessCopilotWidget) {
|
if (component instanceof EdgelessCopilotWidget) {
|
||||||
setupEdgelessCopilot(view.component);
|
setupEdgelessCopilot(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (view.component instanceof EdgelessElementToolbarWidget) {
|
if (component instanceof EdgelessElementToolbarWidget) {
|
||||||
setupEdgelessElementToolbarAIEntry(view.component);
|
setupEdgelessElementToolbarAIEntry(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (view.component instanceof AffineFormatBarWidget) {
|
if (component instanceof AffineFormatBarWidget) {
|
||||||
setupFormatBarAIEntry(view.component);
|
setupFormatBarAIEntry(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (view.component instanceof AffineSlashMenuWidget) {
|
if (component instanceof AffineSlashMenuWidget) {
|
||||||
setupSlashMenuAIEntry(view.component);
|
setupSlashMenuAIEntry(component);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { BlockServiceWatcher } from '@blocksuite/affine/block-std';
|
import { LifeCycleWatcher } from '@blocksuite/affine/block-std';
|
||||||
import {
|
import {
|
||||||
AffineImageToolbarWidget,
|
AffineImageToolbarWidget,
|
||||||
ImageBlockSpec,
|
ImageBlockSpec,
|
||||||
@@ -7,14 +7,19 @@ import type { ExtensionType } from '@blocksuite/affine/store';
|
|||||||
|
|
||||||
import { setupImageToolbarAIEntry } from '../entries/image-toolbar/setup-image-toolbar';
|
import { setupImageToolbarAIEntry } from '../entries/image-toolbar/setup-image-toolbar';
|
||||||
|
|
||||||
class AIImageBlockWatcher extends BlockServiceWatcher {
|
class AIImageBlockWatcher extends LifeCycleWatcher {
|
||||||
static override readonly flavour = 'affine:image';
|
static override key = 'ai-image-block-watcher';
|
||||||
|
|
||||||
override mounted() {
|
override mounted() {
|
||||||
super.mounted();
|
super.mounted();
|
||||||
this.blockService.specSlots.widgetConnected.on(view => {
|
const { view } = this.std;
|
||||||
if (view.component instanceof AffineImageToolbarWidget) {
|
view.viewUpdated.on(payload => {
|
||||||
setupImageToolbarAIEntry(view.component);
|
if (payload.type !== 'widget' || payload.method !== 'add') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const component = payload.view;
|
||||||
|
if (component instanceof AffineImageToolbarWidget) {
|
||||||
|
setupImageToolbarAIEntry(component);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { BlockServiceWatcher } from '@blocksuite/affine/block-std';
|
import { LifeCycleWatcher } from '@blocksuite/affine/block-std';
|
||||||
import {
|
import {
|
||||||
AffineFormatBarWidget,
|
AffineFormatBarWidget,
|
||||||
AffineSlashMenuWidget,
|
AffineSlashMenuWidget,
|
||||||
@@ -17,24 +17,29 @@ import {
|
|||||||
} from '../widgets/ai-panel/ai-panel';
|
} from '../widgets/ai-panel/ai-panel';
|
||||||
|
|
||||||
function getAIPageRootWatcher(framework: FrameworkProvider) {
|
function getAIPageRootWatcher(framework: FrameworkProvider) {
|
||||||
class AIPageRootWatcher extends BlockServiceWatcher {
|
class AIPageRootWatcher extends LifeCycleWatcher {
|
||||||
static override readonly flavour = 'affine:page';
|
static override key = 'ai-page-root-watcher';
|
||||||
|
|
||||||
override mounted() {
|
override mounted() {
|
||||||
super.mounted();
|
super.mounted();
|
||||||
this.blockService.specSlots.widgetConnected.on(view => {
|
const { view } = this.std;
|
||||||
if (view.component instanceof AffineAIPanelWidget) {
|
view.viewUpdated.on(payload => {
|
||||||
view.component.style.width = '630px';
|
if (payload.type !== 'widget' || payload.method !== 'add') {
|
||||||
view.component.config = buildAIPanelConfig(view.component, framework);
|
return;
|
||||||
setupSpaceAIEntry(view.component);
|
}
|
||||||
|
const component = payload.view;
|
||||||
|
if (component instanceof AffineAIPanelWidget) {
|
||||||
|
component.style.width = '630px';
|
||||||
|
component.config = buildAIPanelConfig(component, framework);
|
||||||
|
setupSpaceAIEntry(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (view.component instanceof AffineFormatBarWidget) {
|
if (component instanceof AffineFormatBarWidget) {
|
||||||
setupFormatBarAIEntry(view.component);
|
setupFormatBarAIEntry(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (view.component instanceof AffineSlashMenuWidget) {
|
if (component instanceof AffineSlashMenuWidget) {
|
||||||
setupSlashMenuAIEntry(view.component);
|
setupSlashMenuAIEntry(component);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,16 @@
|
|||||||
import { BlockServiceWatcher } from '@blocksuite/affine/block-std';
|
import { LifeCycleWatcher } from '@blocksuite/affine/block-std';
|
||||||
import {
|
import {
|
||||||
ParagraphBlockService,
|
ParagraphBlockService,
|
||||||
ParagraphBlockSpec,
|
ParagraphBlockSpec,
|
||||||
} from '@blocksuite/affine/blocks';
|
} from '@blocksuite/affine/blocks';
|
||||||
import { assertInstanceOf } from '@blocksuite/affine/global/utils';
|
|
||||||
import type { ExtensionType } from '@blocksuite/affine/store';
|
import type { ExtensionType } from '@blocksuite/affine/store';
|
||||||
|
|
||||||
class AIParagraphBlockWatcher extends BlockServiceWatcher {
|
class AIParagraphBlockWatcher extends LifeCycleWatcher {
|
||||||
static override readonly flavour = 'affine:paragraph';
|
static override key = 'ai-paragraph-block-watcher';
|
||||||
|
|
||||||
override mounted() {
|
override mounted() {
|
||||||
super.mounted();
|
super.mounted();
|
||||||
const service = this.blockService;
|
const service = this.std.get(ParagraphBlockService);
|
||||||
assertInstanceOf(service, ParagraphBlockService);
|
|
||||||
service.placeholderGenerator = model => {
|
service.placeholderGenerator = model => {
|
||||||
if (model.type === 'text') {
|
if (model.type === 'text') {
|
||||||
return "Type '/' for commands, 'space' for AI";
|
return "Type '/' for commands, 'space' for AI";
|
||||||
|
|||||||
@@ -1,27 +1,26 @@
|
|||||||
import { AIChatBlockSchema } from '@affine/core/blocksuite/ai/blocks';
|
import { AIChatBlockSchema } from '@affine/core/blocksuite/ai/blocks';
|
||||||
import { BlockServiceWatcher } from '@blocksuite/affine/block-std';
|
import { LifeCycleWatcher } from '@blocksuite/affine/block-std';
|
||||||
import { EdgelessRootBlockComponent } from '@blocksuite/affine/blocks';
|
import { EdgelessRootBlockComponent } from '@blocksuite/affine/blocks';
|
||||||
import type { BlockSnapshot } from '@blocksuite/affine/store';
|
import type { BlockSnapshot } from '@blocksuite/affine/store';
|
||||||
|
|
||||||
export class EdgelessClipboardWatcher extends BlockServiceWatcher {
|
export class EdgelessClipboardWatcher extends LifeCycleWatcher {
|
||||||
static override readonly flavour = 'affine:page';
|
static override key = 'edgeless-clipboard-watcher';
|
||||||
|
|
||||||
override mounted() {
|
override mounted() {
|
||||||
super.mounted();
|
super.mounted();
|
||||||
this.blockService.disposables.add(
|
const { view } = this.std;
|
||||||
this.blockService.specSlots.viewConnected.on(view => {
|
view.viewUpdated.on(payload => {
|
||||||
const { component } = view;
|
if (payload.type !== 'block' || payload.method !== 'add') {
|
||||||
if (component instanceof EdgelessRootBlockComponent) {
|
return;
|
||||||
|
}
|
||||||
|
const component = payload.view;
|
||||||
|
if (!(component instanceof EdgelessRootBlockComponent)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const AIChatBlockFlavour = AIChatBlockSchema.model.flavour;
|
const AIChatBlockFlavour = AIChatBlockSchema.model.flavour;
|
||||||
const createFunc = (block: BlockSnapshot) => {
|
const createFunc = (block: BlockSnapshot) => {
|
||||||
const {
|
const { xywh, scale, messages, sessionId, rootDocId, rootWorkspaceId } =
|
||||||
xywh,
|
block.props;
|
||||||
scale,
|
|
||||||
messages,
|
|
||||||
sessionId,
|
|
||||||
rootDocId,
|
|
||||||
rootWorkspaceId,
|
|
||||||
} = block.props;
|
|
||||||
const blockId = component.service.crud.addBlock(
|
const blockId = component.service.crud.addBlock(
|
||||||
AIChatBlockFlavour,
|
AIChatBlockFlavour,
|
||||||
{
|
{
|
||||||
@@ -40,8 +39,6 @@ export class EdgelessClipboardWatcher extends BlockServiceWatcher {
|
|||||||
AIChatBlockFlavour,
|
AIChatBlockFlavour,
|
||||||
createFunc
|
createFunc
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,7 @@ import {
|
|||||||
import { ExternalLinksQuickSearchSession } from '@affine/core/modules/quicksearch/impls/external-links';
|
import { ExternalLinksQuickSearchSession } from '@affine/core/modules/quicksearch/impls/external-links';
|
||||||
import { JournalsQuickSearchSession } from '@affine/core/modules/quicksearch/impls/journals';
|
import { JournalsQuickSearchSession } from '@affine/core/modules/quicksearch/impls/journals';
|
||||||
import { track } from '@affine/track';
|
import { track } from '@affine/track';
|
||||||
import {
|
import { LifeCycleWatcher } from '@blocksuite/affine/block-std';
|
||||||
BlockServiceWatcher,
|
|
||||||
type WidgetComponent,
|
|
||||||
} from '@blocksuite/affine/block-std';
|
|
||||||
import type { QuickSearchResult } from '@blocksuite/affine/blocks';
|
import type { QuickSearchResult } from '@blocksuite/affine/blocks';
|
||||||
import {
|
import {
|
||||||
AffineSlashMenuWidget,
|
AffineSlashMenuWidget,
|
||||||
@@ -123,9 +120,17 @@ export function patchQuickSearchService(framework: FrameworkProvider) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const SlashMenuQuickSearchExtension = patchSpecService(
|
class SlashMenuQuickSearchExtension extends LifeCycleWatcher {
|
||||||
'affine:page',
|
static override key = 'slash-menu-quick-search-extension';
|
||||||
(component: WidgetComponent) => {
|
|
||||||
|
override mounted() {
|
||||||
|
super.mounted();
|
||||||
|
const { view } = this.std;
|
||||||
|
view.viewUpdated.on(payload => {
|
||||||
|
if (payload.type !== 'widget' || payload.method !== 'add') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const component = payload.view;
|
||||||
if (component instanceof AffineSlashMenuWidget) {
|
if (component instanceof AffineSlashMenuWidget) {
|
||||||
component.config.items.forEach(item => {
|
component.config.items.forEach(item => {
|
||||||
if (
|
if (
|
||||||
@@ -134,7 +139,9 @@ export function patchQuickSearchService(framework: FrameworkProvider) {
|
|||||||
) {
|
) {
|
||||||
item.action = async ({ rootComponent }) => {
|
item.action = async ({ rootComponent }) => {
|
||||||
const [success, { insertedLinkType }] =
|
const [success, { insertedLinkType }] =
|
||||||
rootComponent.std.command.exec(insertLinkByQuickSearchCommand);
|
rootComponent.std.command.exec(
|
||||||
|
insertLinkByQuickSearchCommand
|
||||||
|
);
|
||||||
|
|
||||||
if (!success) return;
|
if (!success) return;
|
||||||
|
|
||||||
@@ -160,28 +167,9 @@ export function patchQuickSearchService(framework: FrameworkProvider) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
);
|
}
|
||||||
|
|
||||||
return [QuickSearch, SlashMenuQuickSearchExtension];
|
return [QuickSearch, SlashMenuQuickSearchExtension];
|
||||||
}
|
}
|
||||||
|
|
||||||
function patchSpecService(
|
|
||||||
flavour: string,
|
|
||||||
onWidgetConnected?: (component: WidgetComponent) => void
|
|
||||||
) {
|
|
||||||
class TempServiceWatcher extends BlockServiceWatcher {
|
|
||||||
static override readonly flavour = flavour;
|
|
||||||
override mounted() {
|
|
||||||
super.mounted();
|
|
||||||
const disposableGroup = this.blockService.disposables;
|
|
||||||
if (onWidgetConnected) {
|
|
||||||
disposableGroup.add(
|
|
||||||
this.blockService.specSlots.widgetConnected.on(({ component }) => {
|
|
||||||
onWidgetConnected(component);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TempServiceWatcher;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -2,16 +2,14 @@ import { Skeleton } from '@affine/component';
|
|||||||
import type { EditorSettingSchema } from '@affine/core/modules/editor-setting';
|
import type { EditorSettingSchema } from '@affine/core/modules/editor-setting';
|
||||||
import { EditorSettingService } from '@affine/core/modules/editor-setting';
|
import { EditorSettingService } from '@affine/core/modules/editor-setting';
|
||||||
import type { EditorHost } from '@blocksuite/affine/block-std';
|
import type { EditorHost } from '@blocksuite/affine/block-std';
|
||||||
import {
|
import { BlockStdScope } from '@blocksuite/affine/block-std';
|
||||||
BlockServiceIdentifier,
|
|
||||||
BlockStdScope,
|
|
||||||
} from '@blocksuite/affine/block-std';
|
|
||||||
import {
|
import {
|
||||||
GfxControllerIdentifier,
|
GfxControllerIdentifier,
|
||||||
type GfxPrimitiveElementModel,
|
type GfxPrimitiveElementModel,
|
||||||
} from '@blocksuite/affine/block-std/gfx';
|
} from '@blocksuite/affine/block-std/gfx';
|
||||||
import {
|
import {
|
||||||
EdgelessCRUDIdentifier,
|
EdgelessCRUDIdentifier,
|
||||||
|
type EdgelessRootPreviewBlockComponent,
|
||||||
SpecProvider,
|
SpecProvider,
|
||||||
} from '@blocksuite/affine/blocks';
|
} from '@blocksuite/affine/blocks';
|
||||||
import { Bound } from '@blocksuite/affine/global/utils';
|
import { Bound } from '@blocksuite/affine/global/utils';
|
||||||
@@ -93,14 +91,18 @@ export const EdgelessSnapshot = (props: Props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// refresh viewport
|
// refresh viewport
|
||||||
const edgelessService = editorHost.std.get(
|
|
||||||
BlockServiceIdentifier('affine:page')
|
|
||||||
);
|
|
||||||
const gfx = editorHost.std.get(GfxControllerIdentifier);
|
const gfx = editorHost.std.get(GfxControllerIdentifier);
|
||||||
edgelessService.specSlots.viewConnected.once(({ component }) => {
|
const disposable = editorHost.std.view.viewUpdated.on(payload => {
|
||||||
const edgelessBlock = component as any;
|
if (
|
||||||
|
payload.type !== 'block' ||
|
||||||
|
payload.method !== 'add' ||
|
||||||
|
payload.view.model.flavour !== 'affine:page'
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const component = payload.view as EdgelessRootPreviewBlockComponent;
|
||||||
doc.readonly = false;
|
doc.readonly = false;
|
||||||
edgelessBlock.editorViewportSelector = 'ref-viewport';
|
component.editorViewportSelector = 'ref-viewport';
|
||||||
const frame = getFrameBlock(doc);
|
const frame = getFrameBlock(doc);
|
||||||
if (frame && docName !== 'frame') {
|
if (frame && docName !== 'frame') {
|
||||||
// docName with value 'frame' shouldn't be deleted, it is a part of frame settings
|
// docName with value 'frame' shouldn't be deleted, it is a part of frame settings
|
||||||
@@ -110,6 +112,7 @@ export const EdgelessSnapshot = (props: Props) => {
|
|||||||
const bound = boundMap.get(docName);
|
const bound = boundMap.get(docName);
|
||||||
bound && gfx.viewport.setViewportByBound(bound);
|
bound && gfx.viewport.setViewportByBound(bound);
|
||||||
doc.readonly = true;
|
doc.readonly = true;
|
||||||
|
disposable.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
// append to dom node
|
// append to dom node
|
||||||
|
|||||||
Reference in New Issue
Block a user