mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-04 08:38:34 +00:00
#### PR Dependency Tree * **PR #13434** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Style** * Improved clarity of TypeScript error suppression comments across various test files and helper scripts. Comments now specify the reasons for ignoring specific type errors, enhancing code readability for developers. * **Chores** * Updated inline comments without affecting application functionality or user experience. No changes to features, logic, or test outcomes. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
209 lines
5.6 KiB
TypeScript
209 lines
5.6 KiB
TypeScript
import { ViewExtensionManagerIdentifier } from '@blocksuite/affine-ext-loader';
|
|
import {
|
|
DocModeExtension,
|
|
DocModeProvider,
|
|
EditorSettingExtension,
|
|
EditorSettingProvider,
|
|
} from '@blocksuite/affine-shared/services';
|
|
import { BlockStdScope, BlockViewIdentifier } from '@blocksuite/std';
|
|
import type {
|
|
BlockModel,
|
|
BlockViewType,
|
|
ExtensionType,
|
|
Query,
|
|
SliceSnapshot,
|
|
} from '@blocksuite/store';
|
|
import { signal } from '@preact/signals-core';
|
|
import { literal } from 'lit/static-html.js';
|
|
|
|
import { EdgelessDndPreviewElement } from '../components/edgeless-preview/preview.js';
|
|
import type { AffineDragHandleWidget } from '../drag-handle.js';
|
|
|
|
export class PreviewHelper {
|
|
private readonly _calculateQuery = (selectedIds: string[]): Query => {
|
|
const ids: Array<{ id: string; viewType: BlockViewType }> = selectedIds.map(
|
|
id => ({
|
|
id,
|
|
viewType: 'display',
|
|
})
|
|
);
|
|
|
|
// The ancestors of the selected blocks should be rendered as Bypass
|
|
selectedIds.forEach(block => {
|
|
let parent: string | null = block;
|
|
do {
|
|
if (!selectedIds.includes(parent)) {
|
|
ids.push({ viewType: 'bypass', id: parent });
|
|
}
|
|
parent = this.widget.store.getParent(parent)?.id ?? null;
|
|
} while (parent && !ids.map(({ id }) => id).includes(parent));
|
|
});
|
|
|
|
// The children of the selected blocks should be rendered as Display
|
|
const addChildren = (id: string) => {
|
|
const model = this.widget.store.getBlock(id)?.model;
|
|
if (!model) {
|
|
return;
|
|
}
|
|
|
|
const children = model.children ?? [];
|
|
children.forEach(child => {
|
|
ids.push({ viewType: 'display', id: child.id });
|
|
addChildren(child.id);
|
|
});
|
|
};
|
|
selectedIds.forEach(addChildren);
|
|
|
|
return {
|
|
match: ids,
|
|
mode: 'strict',
|
|
};
|
|
};
|
|
|
|
getPreviewStd = (blockIds: string[]) => {
|
|
const widget = this.widget;
|
|
const std = widget.std;
|
|
blockIds = blockIds.slice();
|
|
|
|
const docModeService = std.get(DocModeProvider);
|
|
const editorSetting = std.get(EditorSettingProvider);
|
|
const query = this._calculateQuery(blockIds as string[]);
|
|
const store = widget.store.doc.getStore({ query });
|
|
let previewSpec = widget.std
|
|
.get(ViewExtensionManagerIdentifier)
|
|
.get('preview-page');
|
|
const settingSignal = signal({ ...editorSetting.setting$.peek() });
|
|
const extensions = [
|
|
DocModeExtension(docModeService),
|
|
EditorSettingExtension({ setting$: settingSignal }),
|
|
{
|
|
setup(di) {
|
|
di.override(
|
|
BlockViewIdentifier('affine:database'),
|
|
() => literal`affine-dnd-preview-database`
|
|
);
|
|
},
|
|
} as ExtensionType,
|
|
{
|
|
setup(di) {
|
|
di.override(BlockViewIdentifier('affine:image'), () => {
|
|
return (model: BlockModel) => {
|
|
const parent = model.store.getParent(model.id);
|
|
|
|
if (parent?.flavour === 'affine:surface') {
|
|
return literal`affine-edgeless-placeholder-preview-image`;
|
|
}
|
|
|
|
return literal`affine-placeholder-preview-image`;
|
|
};
|
|
});
|
|
},
|
|
} as ExtensionType,
|
|
];
|
|
|
|
previewSpec = previewSpec.concat(extensions);
|
|
|
|
settingSignal.value = {
|
|
...settingSignal.value,
|
|
edgelessDisableScheduleUpdate: true,
|
|
};
|
|
|
|
const previewStd = new BlockStdScope({
|
|
store,
|
|
extensions: previewSpec,
|
|
});
|
|
|
|
let width: number = 500;
|
|
// oxlint-disable-next-line no-unassigned-vars
|
|
let height;
|
|
|
|
const noteBlock = this.widget.host.querySelector('affine-note');
|
|
width = noteBlock?.offsetWidth ?? noteBlock?.clientWidth ?? 500;
|
|
|
|
return {
|
|
previewStd,
|
|
width,
|
|
height,
|
|
};
|
|
};
|
|
|
|
private _extractBlockTypes(snapshot: SliceSnapshot) {
|
|
const blockTypes: {
|
|
type: string;
|
|
}[] = [];
|
|
|
|
snapshot.content.forEach(block => {
|
|
if (block.flavour === 'affine:surface') {
|
|
Object.values(
|
|
block.props.elements as Record<string, { id: string; type: string }>
|
|
).forEach(elem => {
|
|
blockTypes.push({
|
|
type: elem.type,
|
|
});
|
|
});
|
|
} else {
|
|
blockTypes.push({
|
|
type: block.flavour,
|
|
});
|
|
}
|
|
});
|
|
|
|
return blockTypes;
|
|
}
|
|
|
|
getPreviewElement = (options: {
|
|
blockIds: string[];
|
|
snapshot: SliceSnapshot;
|
|
mode: 'block' | 'gfx';
|
|
}) => {
|
|
const { blockIds, snapshot, mode } = options;
|
|
|
|
if (mode === 'block') {
|
|
const { previewStd, width, height } = this.getPreviewStd(blockIds);
|
|
const previewTemplate = previewStd.render();
|
|
|
|
return {
|
|
width,
|
|
height,
|
|
element: previewTemplate,
|
|
};
|
|
} else {
|
|
const blockTypes = this._extractBlockTypes(snapshot);
|
|
|
|
const edgelessPreview = new EdgelessDndPreviewElement();
|
|
edgelessPreview.elementTypes = blockTypes;
|
|
|
|
return {
|
|
left: 12,
|
|
top: 12,
|
|
element: edgelessPreview,
|
|
};
|
|
}
|
|
};
|
|
|
|
renderDragPreview = (options: {
|
|
blockIds: string[];
|
|
snapshot: SliceSnapshot;
|
|
container: HTMLElement;
|
|
mode: 'block' | 'gfx';
|
|
}): { x: number; y: number } => {
|
|
const { container } = options;
|
|
const { width, height, element, left, top } =
|
|
this.getPreviewElement(options);
|
|
|
|
container.style.position = 'absolute';
|
|
container.style.left = left ? `${left}px` : '';
|
|
container.style.top = top ? `${top}px` : '';
|
|
container.style.width = width ? `${width}px` : '';
|
|
container.style.height = height ? `${height}px` : '';
|
|
container.append(element);
|
|
|
|
return {
|
|
x: left ?? 0,
|
|
y: top ?? 0,
|
|
};
|
|
};
|
|
|
|
constructor(readonly widget: AffineDragHandleWidget) {}
|
|
}
|