diff --git a/blocksuite/affine/blocks/block-code/src/code-toolbar/index.ts b/blocksuite/affine/blocks/block-code/src/code-toolbar/index.ts index 673559d85b..29f72c694f 100644 --- a/blocksuite/affine/blocks/block-code/src/code-toolbar/index.ts +++ b/blocksuite/affine/blocks/block-code/src/code-toolbar/index.ts @@ -35,6 +35,10 @@ export class AffineCodeToolbarWidget extends WidgetComponent< this, ({ abortController }) => { const codeBlock = this.block; + if (!codeBlock) { + return null; + } + const selection = this.host.selection; const textSelection = selection.find(TextSelection); @@ -105,6 +109,9 @@ export class AffineCodeToolbarWidget extends WidgetComponent< ); const codeBlock = this.block; + if (!codeBlock) { + return; + } this._hoverController.setReference(codeBlock); this._hoverController.onAbort = () => { // If the more menu is opened, don't close it. diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/note-slicer/index.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/note-slicer/index.ts index 79f27f61bc..d588969c32 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/note-slicer/index.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/components/note-slicer/index.ts @@ -143,7 +143,7 @@ export class NoteSlicer extends WidgetComponent< } get selectedRectEle() { - return this.block.selectedRectWidget; + return this.block?.selectedRectWidget; } private _sliceNote() { @@ -266,6 +266,10 @@ export class NoteSlicer extends WidgetComponent< this._updateDivingLineAndBlockIds(); + if (!block) { + return; + } + disposables.add( block.slots.elementResizeStart.subscribe(() => { this._isResizing = true; @@ -343,7 +347,7 @@ export class NoteSlicer extends WidgetComponent< } override firstUpdated() { - if (!this.block.service) return; + if (!this.block?.service) return; this.disposables.add( this.block.service.uiEventDispatcher.add('wheel', () => { this._hidden = true; diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/rects/edgeless-dragging-area-rect.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/rects/edgeless-dragging-area-rect.ts index 563f5a84e1..17facc2f3d 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/rects/edgeless-dragging-area-rect.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/components/rects/edgeless-dragging-area-rect.ts @@ -33,6 +33,9 @@ export class EdgelessDraggingAreaRectWidget extends WidgetComponent< `; override render() { + if (!this.block) { + return nothing; + } const rect = this.block.gfx.tool.draggingViewArea$.value; const tool = this.block.gfx.tool.currentTool$.value; diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/rects/edgeless-selected-rect.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/rects/edgeless-selected-rect.ts index 9019df4d01..1d64076732 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/rects/edgeless-selected-rect.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/components/rects/edgeless-selected-rect.ts @@ -477,7 +477,7 @@ export class EdgelessSelectedRectWidget extends WidgetComponent< this._scaleDirection = undefined; this._updateMode(); - this.block.slots.elementResizeEnd.next(); + this.block?.slots.elementResizeEnd.next(); this.frameOverlay.clear(); }; @@ -606,7 +606,7 @@ export class EdgelessSelectedRectWidget extends WidgetComponent< const rotation = this._resizeManager.rotation; this._dragEndCallback = []; - this.block.slots.elementResizeStart.next(); + this.block?.slots.elementResizeStart.next(); this.selection.selectedElements.forEach(el => { el.stash('xywh'); @@ -846,7 +846,7 @@ export class EdgelessSelectedRectWidget extends WidgetComponent< } get edgelessSlots() { - return this.block.slots; + return this.block?.slots; } get frameOverlay() { @@ -1327,41 +1327,46 @@ export class EdgelessSelectedRectWidget extends WidgetComponent< selection.slots.updated.subscribe(this._updateOnSelectionChange) ); - _disposables.add( - block.slots.readonlyUpdated.subscribe(() => this.requestUpdate()) - ); + if (block) { + _disposables.add( + block.slots.readonlyUpdated.subscribe(() => this.requestUpdate()) + ); + + _disposables.add( + block.slots.elementResizeStart.subscribe( + () => (this._isResizing = true) + ) + ); + _disposables.add( + block.slots.elementResizeEnd.subscribe(() => (this._isResizing = false)) + ); + + block.handleEvent( + 'keyDown', + ctx => { + const event = ctx.get('defaultState').event; + if (event instanceof KeyboardEvent) { + this._shift(event); + } + }, + { global: true } + ); + + block.handleEvent( + 'keyUp', + ctx => { + const event = ctx.get('defaultState').event; + if (event instanceof KeyboardEvent) { + this._shift(event); + } + }, + { global: true } + ); + } - _disposables.add( - block.slots.elementResizeStart.subscribe(() => (this._isResizing = true)) - ); - _disposables.add( - block.slots.elementResizeEnd.subscribe(() => (this._isResizing = false)) - ); _disposables.add(() => { this._propDisposables.forEach(disposable => disposable.unsubscribe()); }); - - this.block.handleEvent( - 'keyDown', - ctx => { - const event = ctx.get('defaultState').event; - if (event instanceof KeyboardEvent) { - this._shift(event); - } - }, - { global: true } - ); - - this.block.handleEvent( - 'keyUp', - ctx => { - const event = ctx.get('defaultState').event; - if (event instanceof KeyboardEvent) { - this._shift(event); - } - }, - { global: true } - ); } private _shift(event: KeyboardEvent) { diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/edgeless-toolbar.ts b/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/edgeless-toolbar.ts index 4838c96bec..6e0803bc70 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/edgeless-toolbar.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/components/toolbar/edgeless-toolbar.ts @@ -335,6 +335,9 @@ export class EdgelessToolbarWidget extends WidgetComponent< } private get _quickTools() { + if (!this.block) { + return []; + } return getQuickTools({ edgeless: this.block }); } @@ -376,6 +379,9 @@ export class EdgelessToolbarWidget extends WidgetComponent< } private get _seniorTools() { + if (!this.block) { + return []; + } return getSeniorTools({ edgeless: this.block, toolbarContainer: this.toolbarContainer, @@ -573,6 +579,9 @@ export class EdgelessToolbarWidget extends WidgetComponent< .get(ThemeProvider) .theme$.subscribe(mode => this._themeProvider.setValue(mode)) ); + if (!this.block) { + return; + } this._disposables.add( this.block.bindHotKey( { @@ -603,6 +612,9 @@ export class EdgelessToolbarWidget extends WidgetComponent< override firstUpdated() { const { _disposables, block, gfx } = this; + if (!block) { + return; + } _disposables.add( gfx.viewport.viewportUpdated.subscribe(() => this.requestUpdate()) diff --git a/blocksuite/affine/blocks/block-root/src/widgets/edgeless-zoom-toolbar/index.ts b/blocksuite/affine/blocks/block-root/src/widgets/edgeless-zoom-toolbar/index.ts index 8140623e17..f0dcb24352 100644 --- a/blocksuite/affine/blocks/block-root/src/widgets/edgeless-zoom-toolbar/index.ts +++ b/blocksuite/affine/blocks/block-root/src/widgets/edgeless-zoom-toolbar/index.ts @@ -48,7 +48,7 @@ export class AffineEdgelessZoomToolbarWidget extends WidgetComponent< this.disposables.add( effect(() => { - const currentTool = this.edgeless.gfx.tool.currentToolName$.value; + const currentTool = this.edgeless?.gfx.tool.currentToolName$.value; if (currentTool !== 'frameNavigator') { this._hide = false; diff --git a/blocksuite/affine/blocks/block-root/src/widgets/image-toolbar/index.ts b/blocksuite/affine/blocks/block-root/src/widgets/image-toolbar/index.ts index 342190d3bf..e89b85bc68 100644 --- a/blocksuite/affine/blocks/block-root/src/widgets/image-toolbar/index.ts +++ b/blocksuite/affine/blocks/block-root/src/widgets/image-toolbar/index.ts @@ -37,6 +37,9 @@ export class AffineImageToolbarWidget extends WidgetComponent< this, ({ abortController }) => { const imageBlock = this.block; + if (!imageBlock) { + return null; + } const selection = this.host.selection; const textSelection = selection.find(TextSelection); @@ -103,6 +106,9 @@ export class AffineImageToolbarWidget extends WidgetComponent< ); const imageBlock = this.block; + if (!imageBlock) { + return; + } this._hoverController.setReference(imageBlock); this._hoverController.onAbort = () => { // If the more menu is opened, don't close it. diff --git a/blocksuite/affine/blocks/block-root/src/widgets/keyboard-toolbar/index.ts b/blocksuite/affine/blocks/block-root/src/widgets/keyboard-toolbar/index.ts index cd68e7cb48..82680bf5e4 100644 --- a/blocksuite/affine/blocks/block-root/src/widgets/keyboard-toolbar/index.ts +++ b/blocksuite/affine/blocks/block-root/src/widgets/keyboard-toolbar/index.ts @@ -22,7 +22,7 @@ export class AffineKeyboardToolbarWidget extends WidgetComponent< if (blur) { if (document.activeElement === this._docTitle?.inlineEditorContainer) { this._docTitle?.inlineEditor?.setInlineRange(null); - } else if (document.activeElement === this.block.rootComponent) { + } else if (document.activeElement === this.block?.rootComponent) { this.std.selection.clear(); } } @@ -46,7 +46,7 @@ export class AffineKeyboardToolbarWidget extends WidgetComponent< override connectedCallback(): void { super.connectedCallback(); - const { rootComponent } = this.block; + const rootComponent = this.block?.rootComponent; if (rootComponent) { this.disposables.addFromEvent(rootComponent, 'focus', () => { this._show$.value = true; @@ -79,7 +79,7 @@ export class AffineKeyboardToolbarWidget extends WidgetComponent< if (!this._show$.value) return nothing; - if (!this.block.rootComponent) return nothing; + if (!this.block?.rootComponent) return nothing; return html` { - if (!this.block.rootComponent) return nothing; + if (!this.block?.rootComponent) return nothing; return html` { const surfaceRefBlock = this.block; + if (!surfaceRefBlock) { + return null; + } const selection = this.host.selection; const textSelection = selection.find(TextSelection); @@ -100,6 +103,9 @@ export class AffineSurfaceRefToolbar extends WidgetComponent< super.connectedCallback(); this.moreGroups = getMoreMenuConfig(this.std).configure(this.moreGroups); + if (!this.block) { + return; + } this._hoverController.setReference(this.block); } } diff --git a/blocksuite/affine/widgets/widget-drag-handle/src/watchers/pointer-event-watcher.ts b/blocksuite/affine/widgets/widget-drag-handle/src/watchers/pointer-event-watcher.ts index e72839be45..39284bc7db 100644 --- a/blocksuite/affine/widgets/widget-drag-handle/src/watchers/pointer-event-watcher.ts +++ b/blocksuite/affine/widgets/widget-drag-handle/src/watchers/pointer-event-watcher.ts @@ -161,6 +161,8 @@ export class PointerEventWatcher { if (this.widget.isGfxDragHandleVisible) return; const point = new Point(state.raw.x, state.raw.y); + if (!this.widget.rootComponent) return; + const closestBlock = getClosestBlockByPoint( this.widget.host, this.widget.rootComponent, @@ -246,6 +248,8 @@ export class PointerEventWatcher { // When pointer on drag handle, should do nothing if (element.closest('.affine-drag-handle-container')) return; + if (!this.widget.rootComponent) return; + // When pointer out of note block hover area or inside database, should hide drag handle const point = new Point(state.raw.x, state.raw.y); diff --git a/blocksuite/affine/widgets/widget-edgeless-auto-connect/src/index.ts b/blocksuite/affine/widgets/widget-edgeless-auto-connect/src/index.ts index ff0d071448..12d09ddded 100644 --- a/blocksuite/affine/widgets/widget-edgeless-auto-connect/src/index.ts +++ b/blocksuite/affine/widgets/widget-edgeless-auto-connect/src/index.ts @@ -284,6 +284,9 @@ export class EdgelessAutoConnectWidget extends WidgetComponent { } private _initLabels() { + if (!this.block) { + return; + } const { service } = this.block; const surfaceRefs = service.doc .getBlocksByFlavour('affine:surface-ref') diff --git a/blocksuite/affine/widgets/widget-remote-selection/src/doc/doc-remote-selection.ts b/blocksuite/affine/widgets/widget-remote-selection/src/doc/doc-remote-selection.ts index c6ee41762d..8d52bee02e 100644 --- a/blocksuite/affine/widgets/widget-remote-selection/src/doc/doc-remote-selection.ts +++ b/blocksuite/affine/widgets/widget-remote-selection/src/doc/doc-remote-selection.ts @@ -144,6 +144,10 @@ export class AffineDocRemoteSelectionWidget extends WidgetComponent { } private _getCursorRect(selections: BaseSelection[]): SelectionRect | null { + if (!this.block) { + return null; + } + if (this.block.model.flavour !== 'affine:page') { console.error('remote selection widget must be used in page component'); return null; @@ -208,6 +212,10 @@ export class AffineDocRemoteSelectionWidget extends WidgetComponent { private readonly _getSelectionRect = ( selections: BaseSelection[] ): SelectionRect[] => { + if (!this.block) { + return []; + } + if (this.block.model.flavour !== 'affine:page') { console.error('remote selection widget must be used in page component'); return []; diff --git a/blocksuite/affine/widgets/widget-slash-menu/src/widget.ts b/blocksuite/affine/widgets/widget-slash-menu/src/widget.ts index 07042278b6..22dd4a11b9 100644 --- a/blocksuite/affine/widgets/widget-slash-menu/src/widget.ts +++ b/blocksuite/affine/widgets/widget-slash-menu/src/widget.ts @@ -105,7 +105,7 @@ export class AffineSlashMenuWidget extends WidgetComponent { } }; - if (this.block.model.flavour !== 'affine:page') { + if (this.block?.model.flavour !== 'affine:page') { console.error('SlashMenuWidget should be used in RootBlock'); return; } diff --git a/blocksuite/framework/block-std/src/view/element/widget-component.ts b/blocksuite/framework/block-std/src/view/element/widget-component.ts index 8121f5405d..cb88544e6f 100644 --- a/blocksuite/framework/block-std/src/view/element/widget-component.ts +++ b/blocksuite/framework/block-std/src/view/element/widget-component.ts @@ -28,7 +28,7 @@ export class WidgetComponent< }; get block() { - return this.std.view.getBlock(this.model.id) as B; + return this.std.view.getBlock(this.model.id) as B | null; } get doc() { diff --git a/packages/frontend/core/src/blocksuite/ai/widgets/ai-panel/ai-panel.ts b/packages/frontend/core/src/blocksuite/ai/widgets/ai-panel/ai-panel.ts index e1f5f04c87..e22e662884 100644 --- a/packages/frontend/core/src/blocksuite/ai/widgets/ai-panel/ai-panel.ts +++ b/packages/frontend/core/src/blocksuite/ai/widgets/ai-panel/ai-panel.ts @@ -424,18 +424,20 @@ export class AffineAIPanelWidget extends WidgetComponent { 'pointerdown', this._onDocumentClick ); - this.disposables.add( - this.block.host.event.add('pointerDown', evtState => - this._onDocumentClick( - evtState.get('pointerState').event as PointerEvent + if (this.block) { + this.disposables.add( + this.block.host.event.add('pointerDown', evtState => + this._onDocumentClick( + evtState.get('pointerState').event as PointerEvent + ) ) - ) - ); - this.disposables.add( - this.block.host.event.add('click', () => { - return this.state !== 'hidden' ? true : false; - }) - ); + ); + this.disposables.add( + this.block.host.event.add('click', () => { + return this.state !== 'hidden' ? true : false; + }) + ); + } this.disposables.addFromEvent(this, 'wheel', stopPropagation); this.disposables.addFromEvent(this, 'pointerdown', stopPropagation); this.disposables.addFromEvent(this, 'pointerup', stopPropagation);