mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-13 16:16:46 +08:00
fix(editor): dragging area gets stuck when hovering some embed blocks (#11223)
Close [BS-2778](https://linear.app/affine-design/issue/BS-2778/[bug]-选区框选-html-block-卡顿)
This commit is contained in:
@@ -13,7 +13,7 @@ import { findAncestorModel } from '@blocksuite/affine-shared/utils';
|
||||
import type { BlockService } from '@blocksuite/block-std';
|
||||
import type { GfxCompatibleProps } from '@blocksuite/block-std/gfx';
|
||||
import type { BlockModel } from '@blocksuite/store';
|
||||
import { computed, type ReadonlySignal } from '@preact/signals-core';
|
||||
import { computed, type ReadonlySignal, signal } from '@preact/signals-core';
|
||||
import type { TemplateResult } from 'lit';
|
||||
import { html } from 'lit';
|
||||
import { query } from 'lit/decorators.js';
|
||||
@@ -31,6 +31,17 @@ export class EmbedBlockComponent<
|
||||
})
|
||||
);
|
||||
|
||||
readonly isDraggingOnHost$ = signal(false);
|
||||
readonly isResizing$ = signal(false);
|
||||
// show overlay to prevent the iframe from capturing pointer events
|
||||
// when the block is dragging, resizing, or not selected
|
||||
readonly showOverlay$ = computed(
|
||||
() =>
|
||||
this.isDraggingOnHost$.value ||
|
||||
this.isResizing$.value ||
|
||||
!this.selected$.value
|
||||
);
|
||||
|
||||
private _fetchAbortController = new AbortController();
|
||||
|
||||
_cardStyle: EmbedCardStyle = 'horizontal';
|
||||
@@ -114,6 +125,24 @@ export class EmbedBlockComponent<
|
||||
this._fetchAbortController = new AbortController();
|
||||
|
||||
this.contentEditable = 'false';
|
||||
|
||||
// subscribe the editor host global dragging event
|
||||
// to show the overlay for the dragging area or other pointer events
|
||||
this.handleEvent(
|
||||
'dragStart',
|
||||
() => {
|
||||
this.isDraggingOnHost$.value = true;
|
||||
},
|
||||
{ global: true }
|
||||
);
|
||||
|
||||
this.handleEvent(
|
||||
'dragEnd',
|
||||
() => {
|
||||
this.isDraggingOnHost$.value = false;
|
||||
},
|
||||
{ global: true }
|
||||
);
|
||||
}
|
||||
|
||||
override disconnectedCallback(): void {
|
||||
|
||||
@@ -24,12 +24,6 @@ export function toEdgelessEmbedBlock<
|
||||
return class extends toGfxBlockComponent(block) {
|
||||
override selectedStyle$ = null;
|
||||
|
||||
_isDragging = false;
|
||||
|
||||
_isResizing = false;
|
||||
|
||||
_showOverlay = false;
|
||||
|
||||
override [blockComponentSymbol] = true;
|
||||
|
||||
override blockDraggable = false;
|
||||
@@ -55,16 +49,13 @@ export function toEdgelessEmbedBlock<
|
||||
|
||||
this._disposables.add(
|
||||
this.edgelessSlots.elementResizeStart.subscribe(() => {
|
||||
this._isResizing = true;
|
||||
this._showOverlay = true;
|
||||
this.isResizing$.value = true;
|
||||
})
|
||||
);
|
||||
|
||||
this._disposables.add(
|
||||
this.edgelessSlots.elementResizeEnd.subscribe(() => {
|
||||
this._isResizing = false;
|
||||
this._showOverlay =
|
||||
this._isResizing || this._isDragging || !this.selected$.peek();
|
||||
this.isResizing$.value = false;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import type {
|
||||
} from '@blocksuite/affine-model';
|
||||
import { BlockSelection } from '@blocksuite/block-std';
|
||||
import { html, nothing } from 'lit';
|
||||
import { state } from 'lit/decorators.js';
|
||||
import { classMap } from 'lit/directives/class-map.js';
|
||||
import { styleMap } from 'lit/directives/style-map.js';
|
||||
|
||||
@@ -17,10 +16,6 @@ export class EmbedFigmaBlockComponent extends EmbedBlockComponent<EmbedFigmaMode
|
||||
|
||||
override _cardStyle: (typeof EmbedFigmaStyles)[number] = 'figma';
|
||||
|
||||
protected _isDragging = false;
|
||||
|
||||
protected _isResizing = false;
|
||||
|
||||
open = () => {
|
||||
let link = this.model.props.url;
|
||||
if (!link.match(/^[a-zA-Z]+:\/\//)) {
|
||||
@@ -68,25 +63,6 @@ export class EmbedFigmaBlockComponent extends EmbedBlockComponent<EmbedFigmaMode
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// this is required to prevent iframe from capturing pointer events
|
||||
this.disposables.add(
|
||||
this.selected$.subscribe(selected => {
|
||||
this._showOverlay = this._isResizing || this._isDragging || !selected;
|
||||
})
|
||||
);
|
||||
// this is required to prevent iframe from capturing pointer events
|
||||
this.handleEvent('dragStart', () => {
|
||||
this._isDragging = true;
|
||||
this._showOverlay =
|
||||
this._isResizing || this._isDragging || !this.selected$.peek();
|
||||
});
|
||||
|
||||
this.handleEvent('dragEnd', () => {
|
||||
this._isDragging = false;
|
||||
this._showOverlay =
|
||||
this._isResizing || this._isDragging || !this.selected$.peek();
|
||||
});
|
||||
}
|
||||
|
||||
override renderBlock() {
|
||||
@@ -115,10 +91,11 @@ export class EmbedFigmaBlockComponent extends EmbedBlockComponent<EmbedFigmaMode
|
||||
loading="lazy"
|
||||
></iframe>
|
||||
|
||||
<!-- overlay to prevent the iframe from capturing pointer events -->
|
||||
<div
|
||||
class=${classMap({
|
||||
'affine-embed-figma-iframe-overlay': true,
|
||||
hide: !this._showOverlay,
|
||||
hide: !this.showOverlay$.value,
|
||||
})}
|
||||
></div>
|
||||
</div>
|
||||
@@ -150,7 +127,4 @@ export class EmbedFigmaBlockComponent extends EmbedBlockComponent<EmbedFigmaMode
|
||||
`
|
||||
);
|
||||
}
|
||||
|
||||
@state()
|
||||
protected accessor _showOverlay = true;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { EmbedHtmlModel, EmbedHtmlStyles } from '@blocksuite/affine-model';
|
||||
import { BlockSelection } from '@blocksuite/block-std';
|
||||
import { html } from 'lit';
|
||||
import { query, state } from 'lit/decorators.js';
|
||||
import { query } from 'lit/decorators.js';
|
||||
import { classMap } from 'lit/directives/class-map.js';
|
||||
import { type StyleInfo, styleMap } from 'lit/directives/style-map.js';
|
||||
|
||||
@@ -13,10 +13,6 @@ export class EmbedHtmlBlockComponent extends EmbedBlockComponent<EmbedHtmlModel>
|
||||
|
||||
override _cardStyle: (typeof EmbedHtmlStyles)[number] = 'html';
|
||||
|
||||
protected _isDragging = false;
|
||||
|
||||
protected _isResizing = false;
|
||||
|
||||
close = () => {
|
||||
document.exitFullscreen().catch(console.error);
|
||||
};
|
||||
@@ -50,25 +46,6 @@ export class EmbedHtmlBlockComponent extends EmbedBlockComponent<EmbedHtmlModel>
|
||||
override connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this._cardStyle = this.model.props.style;
|
||||
|
||||
// this is required to prevent iframe from capturing pointer events
|
||||
this.disposables.add(
|
||||
this.selected$.subscribe(selected => {
|
||||
this._showOverlay = this._isResizing || this._isDragging || !selected;
|
||||
})
|
||||
);
|
||||
// this is required to prevent iframe from capturing pointer events
|
||||
this.handleEvent('dragStart', () => {
|
||||
this._isDragging = true;
|
||||
this._showOverlay =
|
||||
this._isResizing || this._isDragging || !this.selected$.peek();
|
||||
});
|
||||
|
||||
this.handleEvent('dragEnd', () => {
|
||||
this._isDragging = false;
|
||||
this._showOverlay =
|
||||
this._isResizing || this._isDragging || !this.selected$.peek();
|
||||
});
|
||||
}
|
||||
|
||||
override renderBlock(): unknown {
|
||||
@@ -112,10 +89,11 @@ export class EmbedHtmlBlockComponent extends EmbedBlockComponent<EmbedHtmlModel>
|
||||
></embed-html-fullscreen-toolbar>
|
||||
</div>
|
||||
|
||||
<!-- overlay to prevent the iframe from capturing pointer events -->
|
||||
<div
|
||||
class=${classMap({
|
||||
'affine-embed-html-iframe-overlay': true,
|
||||
hide: !this._showOverlay,
|
||||
hide: !this.showOverlay$.value,
|
||||
})}
|
||||
></div>
|
||||
</div>
|
||||
@@ -131,9 +109,6 @@ export class EmbedHtmlBlockComponent extends EmbedBlockComponent<EmbedHtmlModel>
|
||||
});
|
||||
}
|
||||
|
||||
@state()
|
||||
protected accessor _showOverlay = true;
|
||||
|
||||
@query('.embed-html-block-iframe-wrapper')
|
||||
accessor iframeWrapper!: HTMLDivElement;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { EmbedLoomModel, EmbedLoomStyles } from '@blocksuite/affine-model';
|
||||
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
||||
import { BlockSelection } from '@blocksuite/block-std';
|
||||
import { html } from 'lit';
|
||||
import { property, state } from 'lit/decorators.js';
|
||||
import { property } from 'lit/decorators.js';
|
||||
import { classMap } from 'lit/directives/class-map.js';
|
||||
import { styleMap } from 'lit/directives/style-map.js';
|
||||
|
||||
@@ -22,10 +22,6 @@ export class EmbedLoomBlockComponent extends EmbedBlockComponent<
|
||||
|
||||
override _cardStyle: (typeof EmbedLoomStyles)[number] = 'video';
|
||||
|
||||
protected _isDragging = false;
|
||||
|
||||
protected _isResizing = false;
|
||||
|
||||
open = () => {
|
||||
let link = this.model.props.url;
|
||||
if (!link.match(/^[a-zA-Z]+:\/\//)) {
|
||||
@@ -89,25 +85,6 @@ export class EmbedLoomBlockComponent extends EmbedBlockComponent<
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// this is required to prevent iframe from capturing pointer events
|
||||
this.disposables.add(
|
||||
this.selected$.subscribe(selected => {
|
||||
this._showOverlay = this._isResizing || this._isDragging || !selected;
|
||||
})
|
||||
);
|
||||
// this is required to prevent iframe from capturing pointer events
|
||||
this.handleEvent('dragStart', () => {
|
||||
this._isDragging = true;
|
||||
this._showOverlay =
|
||||
this._isResizing || this._isDragging || !this.selected$.peek();
|
||||
});
|
||||
|
||||
this.handleEvent('dragEnd', () => {
|
||||
this._isDragging = false;
|
||||
this._showOverlay =
|
||||
this._isResizing || this._isDragging || !this.selected$.peek();
|
||||
});
|
||||
}
|
||||
|
||||
override renderBlock() {
|
||||
@@ -152,10 +129,11 @@ export class EmbedLoomBlockComponent extends EmbedBlockComponent<
|
||||
loading="lazy"
|
||||
></iframe>
|
||||
|
||||
<!-- overlay to prevent the iframe from capturing pointer events -->
|
||||
<div
|
||||
class=${classMap({
|
||||
'affine-embed-loom-video-iframe-overlay': true,
|
||||
hide: !this._showOverlay,
|
||||
hide: !this.showOverlay$.value,
|
||||
})}
|
||||
></div>
|
||||
</div>
|
||||
@@ -188,9 +166,6 @@ export class EmbedLoomBlockComponent extends EmbedBlockComponent<
|
||||
);
|
||||
}
|
||||
|
||||
@state()
|
||||
protected accessor _showOverlay = true;
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor loading = false;
|
||||
}
|
||||
|
||||
+3
-27
@@ -25,10 +25,6 @@ export class EmbedYoutubeBlockComponent extends EmbedBlockComponent<
|
||||
|
||||
override _cardStyle: (typeof EmbedYoutubeStyles)[number] = 'video';
|
||||
|
||||
protected _isDragging = false;
|
||||
|
||||
protected _isResizing = false;
|
||||
|
||||
open = () => {
|
||||
let link = this.model.props.url;
|
||||
if (!link.match(/^[a-zA-Z]+:\/\//)) {
|
||||
@@ -93,25 +89,6 @@ export class EmbedYoutubeBlockComponent extends EmbedBlockComponent<
|
||||
})
|
||||
);
|
||||
|
||||
// this is required to prevent iframe from capturing pointer events
|
||||
this.disposables.add(
|
||||
this.selected$.subscribe(selected => {
|
||||
this._showOverlay = this._isResizing || this._isDragging || !selected;
|
||||
})
|
||||
);
|
||||
// this is required to prevent iframe from capturing pointer events
|
||||
this.handleEvent('dragStart', () => {
|
||||
this._isDragging = true;
|
||||
this._showOverlay =
|
||||
this._isResizing || this._isDragging || !this.selected$.peek();
|
||||
});
|
||||
|
||||
this.handleEvent('dragEnd', () => {
|
||||
this._isDragging = false;
|
||||
this._showOverlay =
|
||||
this._isResizing || this._isDragging || !this.selected$.peek();
|
||||
});
|
||||
|
||||
matchMedia('print').addEventListener('change', () => {
|
||||
this._showImage = matchMedia('print').matches;
|
||||
});
|
||||
@@ -177,10 +154,12 @@ export class EmbedYoutubeBlockComponent extends EmbedBlockComponent<
|
||||
allowfullscreen
|
||||
loading="lazy"
|
||||
></iframe>
|
||||
|
||||
<!-- overlay to prevent the iframe from capturing pointer events -->
|
||||
<div
|
||||
class=${classMap({
|
||||
'affine-embed-youtube-video-iframe-overlay': true,
|
||||
hide: !this._showOverlay,
|
||||
hide: !this.showOverlay$.value,
|
||||
})}
|
||||
></div>
|
||||
<img
|
||||
@@ -242,9 +221,6 @@ export class EmbedYoutubeBlockComponent extends EmbedBlockComponent<
|
||||
@state()
|
||||
private accessor _showImage = false;
|
||||
|
||||
@state()
|
||||
protected accessor _showOverlay = true;
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor loading = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user