import type { BlockCaptionEditor } from '@blocksuite/affine-components/caption'; import { Peekable } from '@blocksuite/affine-components/peek'; import type { ImageBlockModel } from '@blocksuite/affine-model'; import { GfxBlockComponent } from '@blocksuite/block-std'; import { css, html } from 'lit'; import { property, query, state } from 'lit/decorators.js'; import { styleMap } from 'lit/directives/style-map.js'; import { when } from 'lit/directives/when.js'; import type { ImageBlockFallbackCard } from './components/image-block-fallback.js'; import type { ImageBlockService } from './image-service.js'; import { copyImageBlob, downloadImageBlob, fetchImageBlob, resetImageSize, turnImageIntoCardView, } from './utils.js'; @Peekable() export class ImageEdgelessBlockComponent extends GfxBlockComponent< ImageBlockModel, ImageBlockService > { static override styles = css` affine-edgeless-image .resizable-img, affine-edgeless-image .resizable-img img { width: 100%; height: 100%; } `; convertToCardView = () => { turnImageIntoCardView(this).catch(console.error); }; copy = () => { copyImageBlob(this).catch(console.error); }; download = () => { downloadImageBlob(this).catch(console.error); }; refreshData = () => { this.retryCount = 0; fetchImageBlob(this) .then(() => { const { width, height } = this.model; if (!width || !height) { return resetImageSize(this); } return; }) .catch(console.error); }; private _handleError(error: Error) { this.dispatchEvent(new CustomEvent('error', { detail: error })); } override connectedCallback() { super.connectedCallback(); this.refreshData(); this.contentEditable = 'false'; this.disposables.add( this.model.propsUpdated.on(({ key }) => { if (key === 'sourceId') { this.refreshData(); } }) ); } override disconnectedCallback() { if (this.blobUrl) { URL.revokeObjectURL(this.blobUrl); } super.disconnectedCallback(); } override renderGfxBlock() { const rotate = this.model.rotate ?? 0; const containerStyleMap = styleMap({ position: 'relative', width: '100%', transform: `rotate(${rotate}deg)`, transformOrigin: 'center', }); return html`