fix(editor): attachment size in embed view (#12177)

Closes: [BS-3434](https://linear.app/affine-design/issue/BS-3434/修复-attachment-从-card-切换为-embed-尺寸问题)

<img width="1073" alt="Screenshot 2025-05-07 at 20 38 53" src="https://github.com/user-attachments/assets/9fbb7e40-3c01-4473-88d8-3469758ed06b" />

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Added dedicated embed actions for PDF and video attachments, ensuring consistent sizing and improved rendering for these media types.

- **Refactor**
  - Centralized PDF and video embed card dimensions using shared constants for more consistent and maintainable sizing.
  - Improved styling for video embeds, including better layout and responsive sizing.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
fundon
2025-05-07 13:20:51 +00:00
parent 95b9e4b3d0
commit b4f56c0a78
2 changed files with 51 additions and 11 deletions

View File

@@ -3,6 +3,10 @@ import {
type ImageBlockProps, type ImageBlockProps,
MAX_IMAGE_WIDTH, MAX_IMAGE_WIDTH,
} from '@blocksuite/affine-model'; } from '@blocksuite/affine-model';
import {
EMBED_CARD_HEIGHT,
EMBED_CARD_WIDTH,
} from '@blocksuite/affine-shared/consts';
import { FileSizeLimitProvider } from '@blocksuite/affine-shared/services'; import { FileSizeLimitProvider } from '@blocksuite/affine-shared/services';
import { import {
readImageSize, readImageSize,
@@ -17,6 +21,7 @@ import type { ExtensionType } from '@blocksuite/store';
import { Extension } from '@blocksuite/store'; import { Extension } from '@blocksuite/store';
import type { TemplateResult } from 'lit'; import type { TemplateResult } from 'lit';
import { html } from 'lit'; import { html } from 'lit';
import { styleMap } from 'lit/directives/style-map.js';
import { getAttachmentBlob } from './utils'; import { getAttachmentBlob } from './utils';
@@ -97,11 +102,13 @@ export class AttachmentEmbedService extends Extension {
// Converts to embed view. // Converts to embed view.
convertTo(model: AttachmentBlockModel, maxFileSize = this._maxFileSize) { convertTo(model: AttachmentBlockModel, maxFileSize = this._maxFileSize) {
const config = this.values.find(config => config.check(model, maxFileSize)); const config = this.values.find(config => config.check(model, maxFileSize));
if (!config?.action) {
model.store.updateBlock(model, { embed: true }); if (config?.action) {
config.action(model, this.std)?.catch(console.error);
return; return;
} }
config.action(model, this.std)?.catch(console.error);
model.store.updateBlock(model, { embed: true });
} }
embedded(model: AttachmentBlockModel, maxFileSize = this._maxFileSize) { embedded(model: AttachmentBlockModel, maxFileSize = this._maxFileSize) {
@@ -142,14 +149,27 @@ const embedConfig: AttachmentEmbedConfig[] = [
name: 'pdf', name: 'pdf',
check: (model, maxFileSize) => check: (model, maxFileSize) =>
model.props.type === 'application/pdf' && model.props.size <= maxFileSize, model.props.type === 'application/pdf' && model.props.size <= maxFileSize,
action: model => {
const bound = Bound.deserialize(model.props.xywh);
bound.w = EMBED_CARD_WIDTH.pdf;
bound.h = EMBED_CARD_HEIGHT.pdf;
model.store.updateBlock(model, {
embed: true,
style: 'pdf',
xywh: bound.serialize(),
});
},
template: (_, blobUrl) => { template: (_, blobUrl) => {
// More options: https://tinytip.co/tips/html-pdf-params/ // More options: https://tinytip.co/tips/html-pdf-params/
// https://chromium.googlesource.com/chromium/src/+/refs/tags/121.0.6153.1/chrome/browser/resources/pdf/open_pdf_params_parser.ts // https://chromium.googlesource.com/chromium/src/+/refs/tags/121.0.6153.1/chrome/browser/resources/pdf/open_pdf_params_parser.ts
const parameters = '#toolbar=0'; const parameters = '#toolbar=0';
return html` return html`
<iframe <iframe
style="width: 100%; color-scheme: auto;" style=${styleMap({
height="480" width: '100%',
minHeight: '480px',
colorScheme: 'auto',
})}
src=${blobUrl + parameters} src=${blobUrl + parameters}
loading="lazy" loading="lazy"
scrolling="no" scrolling="no"
@@ -167,13 +187,29 @@ const embedConfig: AttachmentEmbedConfig[] = [
name: 'video', name: 'video',
check: (model, maxFileSize) => check: (model, maxFileSize) =>
model.props.type.startsWith('video/') && model.props.size <= maxFileSize, model.props.type.startsWith('video/') && model.props.size <= maxFileSize,
action: model => {
const bound = Bound.deserialize(model.props.xywh);
bound.w = EMBED_CARD_WIDTH.video;
bound.h = EMBED_CARD_HEIGHT.video;
model.store.updateBlock(model, {
embed: true,
style: 'video',
xywh: bound.serialize(),
});
},
template: (_, blobUrl) => template: (_, blobUrl) =>
html`<video html`<video
style="max-height: max-content;" style=${styleMap({
width="100%;" display: 'flex',
height="480" objectFit: 'cover',
controls backgroundSize: 'cover',
width: '100%',
height: '100%',
})}
src=${blobUrl} src=${blobUrl}
width="100%"
height="100%"
controls
></video>`, ></video>`,
}, },
{ {

View File

@@ -2,6 +2,10 @@ import type { ReactToLit } from '@affine/component';
import { AttachmentEmbedPreview } from '@affine/core/blocksuite/attachment-viewer/attachment-embed-preview'; import { AttachmentEmbedPreview } from '@affine/core/blocksuite/attachment-viewer/attachment-embed-preview';
import { AttachmentEmbedConfigIdentifier } from '@blocksuite/affine/blocks/attachment'; import { AttachmentEmbedConfigIdentifier } from '@blocksuite/affine/blocks/attachment';
import { Bound } from '@blocksuite/affine/global/gfx'; import { Bound } from '@blocksuite/affine/global/gfx';
import {
EMBED_CARD_HEIGHT,
EMBED_CARD_WIDTH,
} from '@blocksuite/affine/shared/consts';
import type { ExtensionType } from '@blocksuite/affine/store'; import type { ExtensionType } from '@blocksuite/affine/store';
export function patchForPDFEmbedView(reactToLit: ReactToLit): ExtensionType { export function patchForPDFEmbedView(reactToLit: ReactToLit): ExtensionType {
@@ -14,8 +18,8 @@ export function patchForPDFEmbedView(reactToLit: ReactToLit): ExtensionType {
model.props.size <= maxFileSize, model.props.size <= maxFileSize,
action: model => { action: model => {
const bound = Bound.deserialize(model.props.xywh); const bound = Bound.deserialize(model.props.xywh);
bound.w = 537 + 24 + 2; bound.w = EMBED_CARD_WIDTH.pdf;
bound.h = 759 + 46 + 24 + 2; bound.h = EMBED_CARD_HEIGHT.pdf;
model.store.updateBlock(model, { model.store.updateBlock(model, {
embed: true, embed: true,
style: 'pdf', style: 'pdf',