mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-10 21:48:48 +08:00
refactor(editor): move export manager to surface block extensions (#10231)
This commit is contained in:
@@ -24,9 +24,11 @@
|
|||||||
"@preact/signals-core": "^1.8.0",
|
"@preact/signals-core": "^1.8.0",
|
||||||
"@toeverything/theme": "^1.1.7",
|
"@toeverything/theme": "^1.1.7",
|
||||||
"fractional-indexing": "^3.2.0",
|
"fractional-indexing": "^3.2.0",
|
||||||
|
"html2canvas": "^1.4.1",
|
||||||
"lit": "^3.2.0",
|
"lit": "^3.2.0",
|
||||||
"lodash.chunk": "^4.2.0",
|
"lodash.chunk": "^4.2.0",
|
||||||
"nanoid": "^5.0.7",
|
"nanoid": "^5.0.7",
|
||||||
|
"pdf-lib": "^1.17.1",
|
||||||
"yjs": "^13.6.21",
|
"yjs": "^13.6.21",
|
||||||
"zod": "^3.23.8"
|
"zod": "^3.23.8"
|
||||||
},
|
},
|
||||||
|
|||||||
+87
-27
@@ -1,11 +1,8 @@
|
|||||||
import {
|
|
||||||
type CanvasRenderer,
|
|
||||||
SurfaceElementModel,
|
|
||||||
} from '@blocksuite/affine-block-surface';
|
|
||||||
import {
|
import {
|
||||||
FrameBlockModel,
|
FrameBlockModel,
|
||||||
GroupElementModel,
|
GroupElementModel,
|
||||||
ImageBlockModel,
|
ImageBlockModel,
|
||||||
|
type NoteBlockModel,
|
||||||
type RootBlockModel,
|
type RootBlockModel,
|
||||||
} from '@blocksuite/affine-model';
|
} from '@blocksuite/affine-model';
|
||||||
import { FetchUtils } from '@blocksuite/affine-shared/adapters';
|
import { FetchUtils } from '@blocksuite/affine-shared/adapters';
|
||||||
@@ -13,32 +10,32 @@ import {
|
|||||||
CANVAS_EXPORT_IGNORE_TAGS,
|
CANVAS_EXPORT_IGNORE_TAGS,
|
||||||
DEFAULT_IMAGE_PROXY_ENDPOINT,
|
DEFAULT_IMAGE_PROXY_ENDPOINT,
|
||||||
} from '@blocksuite/affine-shared/consts';
|
} from '@blocksuite/affine-shared/consts';
|
||||||
|
import type { Viewport } from '@blocksuite/affine-shared/types';
|
||||||
import {
|
import {
|
||||||
isInsidePageEditor,
|
isInsidePageEditor,
|
||||||
matchModels,
|
matchModels,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} from '@blocksuite/affine-shared/utils';
|
||||||
import {
|
import {
|
||||||
|
type BlockComponent,
|
||||||
type BlockStdScope,
|
type BlockStdScope,
|
||||||
type EditorHost,
|
type EditorHost,
|
||||||
StdIdentifier,
|
StdIdentifier,
|
||||||
} from '@blocksuite/block-std';
|
} from '@blocksuite/block-std';
|
||||||
import type {
|
import {
|
||||||
GfxBlockElementModel,
|
GfxBlockElementModel,
|
||||||
GfxPrimitiveElementModel,
|
type GfxController,
|
||||||
|
GfxControllerIdentifier,
|
||||||
|
type GfxPrimitiveElementModel,
|
||||||
} from '@blocksuite/block-std/gfx';
|
} from '@blocksuite/block-std/gfx';
|
||||||
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
|
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
|
||||||
import type { IBound } from '@blocksuite/global/utils';
|
import type { IBound } from '@blocksuite/global/utils';
|
||||||
import { Bound } from '@blocksuite/global/utils';
|
import { Bound, deserializeXYWH } from '@blocksuite/global/utils';
|
||||||
import type { ExtensionType, Store } from '@blocksuite/store';
|
import type { ExtensionType, Store } from '@blocksuite/store';
|
||||||
|
|
||||||
import {
|
import { SurfaceElementModel } from '../../element-model/base.js';
|
||||||
getBlockComponentByModel,
|
import type { CanvasRenderer } from '../../renderer/canvas-renderer.js';
|
||||||
getRootByEditorHost,
|
import type { SurfaceBlockComponent } from '../../surface-block.js';
|
||||||
} from '../../_common/utils/index.js';
|
import { getBgGridGap } from '../../utils/get-bg-grip-gap.js';
|
||||||
import type { EdgelessRootBlockComponent } from '../../root-block/edgeless/edgeless-root-block.js';
|
|
||||||
import { getBlocksInFrameBound } from '../../root-block/edgeless/frame-manager.js';
|
|
||||||
import { xywhArrayToObject } from '../../root-block/edgeless/utils/convert.js';
|
|
||||||
import { getBackgroundGrid } from '../../root-block/edgeless/utils/query.js';
|
|
||||||
import { FileExporter } from './file-exporter.js';
|
import { FileExporter } from './file-exporter.js';
|
||||||
|
|
||||||
// oxlint-disable-next-line typescript/consistent-type-imports
|
// oxlint-disable-next-line typescript/consistent-type-imports
|
||||||
@@ -47,6 +44,7 @@ type Html2CanvasFunction = typeof import('html2canvas').default;
|
|||||||
export type ExportOptions = {
|
export type ExportOptions = {
|
||||||
imageProxyEndpoint: string;
|
imageProxyEndpoint: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class ExportManager {
|
export class ExportManager {
|
||||||
private readonly _exportOptions: ExportOptions = {
|
private readonly _exportOptions: ExportOptions = {
|
||||||
imageProxyEndpoint: DEFAULT_IMAGE_PROXY_ENDPOINT,
|
imageProxyEndpoint: DEFAULT_IMAGE_PROXY_ENDPOINT,
|
||||||
@@ -151,7 +149,9 @@ export class ExportManager {
|
|||||||
}
|
}
|
||||||
const rootModel = this.doc.root;
|
const rootModel = this.doc.root;
|
||||||
const rootComponent = this.doc.root
|
const rootComponent = this.doc.root
|
||||||
? getBlockComponentByModel(this.editorHost, rootModel)
|
? rootModel
|
||||||
|
? this.editorHost.view.getBlock(rootModel.id)
|
||||||
|
: null
|
||||||
: null;
|
: null;
|
||||||
const imageCard = rootComponent?.querySelector(
|
const imageCard = rootComponent?.querySelector(
|
||||||
'affine-image-fallback-card'
|
'affine-image-fallback-card'
|
||||||
@@ -398,12 +398,11 @@ export class ExportManager {
|
|||||||
const rootModel = this.doc.root;
|
const rootModel = this.doc.root;
|
||||||
if (!rootModel) return;
|
if (!rootModel) return;
|
||||||
|
|
||||||
const edgeless = getBlockComponentByModel(
|
const gfx = this.editorHost.std.get(GfxControllerIdentifier);
|
||||||
this.editorHost,
|
const surfaceBlock = gfx.surfaceComponent as SurfaceBlockComponent | null;
|
||||||
rootModel
|
if (!surfaceBlock) return;
|
||||||
) as EdgelessRootBlockComponent;
|
const bound = gfx.elementsBound;
|
||||||
const bound = edgeless.gfx.elementsBound;
|
return this.edgelessToCanvas(surfaceBlock.renderer, bound, gfx);
|
||||||
return this.edgelessToCanvas(edgeless.surface.renderer, bound, edgeless);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,7 +410,7 @@ export class ExportManager {
|
|||||||
async edgelessToCanvas(
|
async edgelessToCanvas(
|
||||||
surfaceRenderer: CanvasRenderer,
|
surfaceRenderer: CanvasRenderer,
|
||||||
bound: IBound,
|
bound: IBound,
|
||||||
edgeless?: EdgelessRootBlockComponent,
|
gfx: GfxController,
|
||||||
nodes?: GfxBlockElementModel[],
|
nodes?: GfxBlockElementModel[],
|
||||||
surfaces?: GfxPrimitiveElementModel[],
|
surfaces?: GfxPrimitiveElementModel[],
|
||||||
edgelessBackground?: {
|
edgelessBackground?: {
|
||||||
@@ -449,7 +448,7 @@ export class ExportManager {
|
|||||||
backgroundColor: containerComputedStyle.getPropertyValue(
|
backgroundColor: containerComputedStyle.getPropertyValue(
|
||||||
'--affine-background-primary-color'
|
'--affine-background-primary-color'
|
||||||
),
|
),
|
||||||
size: getBackgroundGrid(edgelessBackground.zoom, true).gap,
|
size: getBgGridGap(edgelessBackground.zoom),
|
||||||
gridColor: containerComputedStyle.getPropertyValue(
|
gridColor: containerComputedStyle.getPropertyValue(
|
||||||
'--affine-edgeless-grid-color'
|
'--affine-edgeless-grid-color'
|
||||||
),
|
),
|
||||||
@@ -457,9 +456,7 @@ export class ExportManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const blocks =
|
const blocks =
|
||||||
nodes ??
|
nodes ?? gfx.getElementsByBound(bound, { type: 'block' }) ?? [];
|
||||||
edgeless?.service.gfx.getElementsByBound(bound, { type: 'block' }) ??
|
|
||||||
[];
|
|
||||||
for (const block of blocks) {
|
for (const block of blocks) {
|
||||||
if (matchModels(block, [ImageBlockModel])) {
|
if (matchModels(block, [ImageBlockModel])) {
|
||||||
if (!block.sourceId) return;
|
if (!block.sourceId) return;
|
||||||
@@ -592,3 +589,66 @@ export const ExportManagerExtension: ExtensionType = {
|
|||||||
di.add(ExportManager, [StdIdentifier]);
|
di.add(ExportManager, [StdIdentifier]);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function xywhArrayToObject(element: GfxBlockElementModel) {
|
||||||
|
const [x, y, w, h] = deserializeXYWH(element.xywh);
|
||||||
|
return { x, y, w, h };
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNotesInFrameBound(
|
||||||
|
doc: Store,
|
||||||
|
frame: FrameBlockModel,
|
||||||
|
fullyContained: boolean = true
|
||||||
|
): NoteBlockModel[] {
|
||||||
|
const bound = Bound.deserialize(frame.xywh);
|
||||||
|
|
||||||
|
return (doc.getBlockByFlavour('affine:note') as NoteBlockModel[]).filter(
|
||||||
|
ele => {
|
||||||
|
const xywh = Bound.deserialize(ele.xywh);
|
||||||
|
|
||||||
|
return fullyContained
|
||||||
|
? bound.contains(xywh)
|
||||||
|
: bound.isPointInBound([xywh.x, xywh.y]);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBlocksInFrameBound(
|
||||||
|
doc: Store,
|
||||||
|
model: FrameBlockModel,
|
||||||
|
fullyContained: boolean = true
|
||||||
|
) {
|
||||||
|
const bound = Bound.deserialize(model.xywh);
|
||||||
|
const surface = model.surface;
|
||||||
|
if (!surface) return [];
|
||||||
|
|
||||||
|
return (
|
||||||
|
getNotesInFrameBound(doc, model, fullyContained) as GfxBlockElementModel[]
|
||||||
|
).concat(
|
||||||
|
surface.children.filter((ele): ele is GfxBlockElementModel => {
|
||||||
|
if (ele.id === model.id) return false;
|
||||||
|
if (ele instanceof GfxBlockElementModel) {
|
||||||
|
const blockBound = Bound.deserialize(ele.xywh);
|
||||||
|
return fullyContained
|
||||||
|
? bound.contains(blockBound)
|
||||||
|
: bound.containsPoint([blockBound.x, blockBound.y]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
type RootBlockComponent = BlockComponent & {
|
||||||
|
viewportElement: HTMLElement;
|
||||||
|
viewport: Viewport;
|
||||||
|
};
|
||||||
|
|
||||||
|
function getRootByEditorHost(
|
||||||
|
editorHost: EditorHost
|
||||||
|
): RootBlockComponent | null {
|
||||||
|
const model = editorHost.doc.root;
|
||||||
|
if (!model) return null;
|
||||||
|
const root = editorHost.view.getBlock(model.id);
|
||||||
|
return root as RootBlockComponent | null;
|
||||||
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* eslint-disable no-control-regex */
|
/* oxlint-disable no-control-regex */
|
||||||
// Context: Lean towards breaking out any localizable content into constants so it's
|
// Context: Lean towards breaking out any localizable content into constants so it's
|
||||||
// easier to track content we may need to localize in the future. (i18n)
|
// easier to track content we may need to localize in the future. (i18n)
|
||||||
const UNTITLED_PAGE_NAME = 'Untitled';
|
const UNTITLED_PAGE_NAME = 'Untitled';
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { ExportManager, ExportManagerExtension } from './export-manager.js';
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
export * from './crud-extension';
|
export * from './crud-extension';
|
||||||
|
export * from './export-manager';
|
||||||
export * from './legacy-slot-extension';
|
export * from './legacy-slot-extension';
|
||||||
export * from './query';
|
export * from './query';
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ export {
|
|||||||
addNote,
|
addNote,
|
||||||
addNoteAtPoint,
|
addNoteAtPoint,
|
||||||
generateElementId,
|
generateElementId,
|
||||||
|
getBgGridGap,
|
||||||
getLastPropsKey,
|
getLastPropsKey,
|
||||||
getSurfaceBlock,
|
getSurfaceBlock,
|
||||||
normalizeWheelDeltaY,
|
normalizeWheelDeltaY,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
EdgelessCRUDExtension,
|
EdgelessCRUDExtension,
|
||||||
EdgelessLegacySlotExtension,
|
EdgelessLegacySlotExtension,
|
||||||
} from './extensions';
|
} from './extensions';
|
||||||
|
import { ExportManagerExtension } from './extensions/export-manager/export-manager';
|
||||||
import { SurfaceBlockService } from './surface-service';
|
import { SurfaceBlockService } from './surface-service';
|
||||||
import { MindMapView } from './view/mindmap';
|
import { MindMapView } from './view/mindmap';
|
||||||
|
|
||||||
@@ -19,6 +20,7 @@ const CommonSurfaceBlockSpec: ExtensionType[] = [
|
|||||||
MindMapView,
|
MindMapView,
|
||||||
EdgelessCRUDExtension,
|
EdgelessCRUDExtension,
|
||||||
EdgelessLegacySlotExtension,
|
EdgelessLegacySlotExtension,
|
||||||
|
ExportManagerExtension,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const PageSurfaceBlockSpec: ExtensionType[] = [
|
export const PageSurfaceBlockSpec: ExtensionType[] = [
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { clamp } from '@blocksuite/global/utils';
|
||||||
|
|
||||||
|
import { GRID_GAP_MAX, GRID_GAP_MIN } from '../consts';
|
||||||
|
|
||||||
|
export function getBgGridGap(zoom: number) {
|
||||||
|
const step = zoom < 0.5 ? 2 : 1 / (Math.floor(zoom) || 1);
|
||||||
|
const gap = clamp(20 * step * zoom, GRID_GAP_MIN, GRID_GAP_MAX);
|
||||||
|
|
||||||
|
return gap;
|
||||||
|
}
|
||||||
@@ -34,6 +34,7 @@ export function normalizeWheelDeltaY(delta: number, zoom = 1) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export { addNote, addNoteAtPoint } from './add-note';
|
export { addNote, addNoteAtPoint } from './add-note';
|
||||||
|
export { getBgGridGap } from './get-bg-grip-gap';
|
||||||
export { getLastPropsKey } from './get-last-props-key';
|
export { getLastPropsKey } from './get-last-props-key';
|
||||||
export { getSurfaceBlock } from './get-surface-block';
|
export { getSurfaceBlock } from './get-surface-block';
|
||||||
export * from './mindmap/style-svg.js';
|
export * from './mindmap/style-svg.js';
|
||||||
|
|||||||
@@ -62,7 +62,6 @@
|
|||||||
"lz-string": "^1.5.0",
|
"lz-string": "^1.5.0",
|
||||||
"minimatch": "^10.0.1",
|
"minimatch": "^10.0.1",
|
||||||
"nanoid": "^5.0.7",
|
"nanoid": "^5.0.7",
|
||||||
"pdf-lib": "^1.17.1",
|
|
||||||
"shiki": "^2.0.0",
|
"shiki": "^2.0.0",
|
||||||
"simple-xml-to-json": "^1.2.2",
|
"simple-xml-to-json": "^1.2.2",
|
||||||
"yjs": "^13.6.21",
|
"yjs": "^13.6.21",
|
||||||
|
|||||||
@@ -8,10 +8,6 @@ import { isCanvasElement } from './root-block/edgeless/utils/query.js';
|
|||||||
|
|
||||||
export * from './_common/adapters/index.js';
|
export * from './_common/adapters/index.js';
|
||||||
export { type NavigatorMode } from './_common/edgeless/frame/consts.js';
|
export { type NavigatorMode } from './_common/edgeless/frame/consts.js';
|
||||||
export {
|
|
||||||
ExportManager,
|
|
||||||
ExportManagerExtension,
|
|
||||||
} from './_common/export-manager/export-manager.js';
|
|
||||||
export * from './_common/test-utils/test-utils.js';
|
export * from './_common/test-utils/test-utils.js';
|
||||||
export * from './_common/transformers/index.js';
|
export * from './_common/transformers/index.js';
|
||||||
export { type AbstractEditor } from './_common/types.js';
|
export { type AbstractEditor } from './_common/types.js';
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import {
|
|||||||
import { FlavourExtension } from '@blocksuite/block-std';
|
import { FlavourExtension } from '@blocksuite/block-std';
|
||||||
import type { ExtensionType } from '@blocksuite/store';
|
import type { ExtensionType } from '@blocksuite/store';
|
||||||
|
|
||||||
import { ExportManagerExtension } from '../../_common/export-manager/export-manager';
|
|
||||||
import { RootBlockAdapterExtensions } from '../adapters/extension';
|
import { RootBlockAdapterExtensions } from '../adapters/extension';
|
||||||
import {
|
import {
|
||||||
docRemoteSelectionWidget,
|
docRemoteSelectionWidget,
|
||||||
@@ -29,7 +28,6 @@ export const CommonSpecs: ExtensionType[] = [
|
|||||||
DocModeService,
|
DocModeService,
|
||||||
ThemeService,
|
ThemeService,
|
||||||
EmbedOptionService,
|
EmbedOptionService,
|
||||||
ExportManagerExtension,
|
|
||||||
PageViewportServiceExtension,
|
PageViewportServiceExtension,
|
||||||
DNDAPIExtension,
|
DNDAPIExtension,
|
||||||
FileDropExtension,
|
FileDropExtension,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { addImages } from '@blocksuite/affine-block-image';
|
|||||||
import {
|
import {
|
||||||
CanvasElementType,
|
CanvasElementType,
|
||||||
EdgelessCRUDIdentifier,
|
EdgelessCRUDIdentifier,
|
||||||
|
ExportManager,
|
||||||
SurfaceGroupLikeModel,
|
SurfaceGroupLikeModel,
|
||||||
TextUtils,
|
TextUtils,
|
||||||
} from '@blocksuite/affine-block-surface';
|
} from '@blocksuite/affine-block-surface';
|
||||||
@@ -68,7 +69,6 @@ import {
|
|||||||
import DOMPurify from 'dompurify';
|
import DOMPurify from 'dompurify';
|
||||||
import * as Y from 'yjs';
|
import * as Y from 'yjs';
|
||||||
|
|
||||||
import { ExportManager } from '../../../_common/export-manager/export-manager.js';
|
|
||||||
import { getRootByEditorHost } from '../../../_common/utils/query.js';
|
import { getRootByEditorHost } from '../../../_common/utils/query.js';
|
||||||
import { ClipboardAdapter } from '../../clipboard/adapter.js';
|
import { ClipboardAdapter } from '../../clipboard/adapter.js';
|
||||||
import { PageClipboard } from '../../clipboard/index.js';
|
import { PageClipboard } from '../../clipboard/index.js';
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import type {
|
|||||||
} from '@blocksuite/affine-block-surface';
|
} from '@blocksuite/affine-block-surface';
|
||||||
import {
|
import {
|
||||||
EdgelessLegacySlotIdentifier,
|
EdgelessLegacySlotIdentifier,
|
||||||
|
getBgGridGap,
|
||||||
normalizeWheelDeltaY,
|
normalizeWheelDeltaY,
|
||||||
} from '@blocksuite/affine-block-surface';
|
} from '@blocksuite/affine-block-surface';
|
||||||
import {
|
import {
|
||||||
@@ -51,7 +52,7 @@ import { EdgelessClipboardController } from './clipboard/clipboard.js';
|
|||||||
import type { EdgelessSelectedRectWidget } from './components/rects/edgeless-selected-rect.js';
|
import type { EdgelessSelectedRectWidget } from './components/rects/edgeless-selected-rect.js';
|
||||||
import { EdgelessPageKeyboardManager } from './edgeless-keyboard.js';
|
import { EdgelessPageKeyboardManager } from './edgeless-keyboard.js';
|
||||||
import type { EdgelessRootService } from './edgeless-root-service.js';
|
import type { EdgelessRootService } from './edgeless-root-service.js';
|
||||||
import { getBackgroundGrid, isCanvasElement } from './utils/query.js';
|
import { isCanvasElement } from './utils/query.js';
|
||||||
import { mountShapeTextEditor } from './utils/text.js';
|
import { mountShapeTextEditor } from './utils/text.js';
|
||||||
|
|
||||||
export class EdgelessRootBlockComponent extends BlockComponent<
|
export class EdgelessRootBlockComponent extends BlockComponent<
|
||||||
@@ -106,7 +107,7 @@ export class EdgelessRootBlockComponent extends BlockComponent<
|
|||||||
private readonly _refreshLayerViewport = requestThrottledConnectedFrame(
|
private readonly _refreshLayerViewport = requestThrottledConnectedFrame(
|
||||||
() => {
|
() => {
|
||||||
const { zoom, translateX, translateY } = this.gfx.viewport;
|
const { zoom, translateX, translateY } = this.gfx.viewport;
|
||||||
const { gap } = getBackgroundGrid(zoom, true);
|
const gap = getBgGridGap(zoom);
|
||||||
|
|
||||||
if (this.backgroundElm) {
|
if (this.backgroundElm) {
|
||||||
this.backgroundElm.style.setProperty(
|
this.backgroundElm.style.setProperty(
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type {
|
import {
|
||||||
SurfaceBlockComponent,
|
getBgGridGap,
|
||||||
SurfaceBlockModel,
|
type SurfaceBlockComponent,
|
||||||
|
type SurfaceBlockModel,
|
||||||
} from '@blocksuite/affine-block-surface';
|
} from '@blocksuite/affine-block-surface';
|
||||||
import type { EdgelessPreviewer } from '@blocksuite/affine-block-surface-ref';
|
import type { EdgelessPreviewer } from '@blocksuite/affine-block-surface-ref';
|
||||||
import type { RootBlockModel } from '@blocksuite/affine-model';
|
import type { RootBlockModel } from '@blocksuite/affine-model';
|
||||||
@@ -23,7 +24,7 @@ import { styleMap } from 'lit/directives/style-map.js';
|
|||||||
|
|
||||||
import type { EdgelessRootBlockWidgetName } from '../types.js';
|
import type { EdgelessRootBlockWidgetName } from '../types.js';
|
||||||
import type { EdgelessRootService } from './edgeless-root-service.js';
|
import type { EdgelessRootService } from './edgeless-root-service.js';
|
||||||
import { getBackgroundGrid, isCanvasElement } from './utils/query.js';
|
import { isCanvasElement } from './utils/query.js';
|
||||||
|
|
||||||
export class EdgelessRootPreviewBlockComponent
|
export class EdgelessRootPreviewBlockComponent
|
||||||
extends BlockComponent<
|
extends BlockComponent<
|
||||||
@@ -73,7 +74,7 @@ export class EdgelessRootPreviewBlockComponent
|
|||||||
private readonly _refreshLayerViewport = requestThrottledConnectedFrame(
|
private readonly _refreshLayerViewport = requestThrottledConnectedFrame(
|
||||||
() => {
|
() => {
|
||||||
const { zoom, translateX, translateY } = this.service.viewport;
|
const { zoom, translateX, translateY } = this.service.viewport;
|
||||||
const { gap } = getBackgroundGrid(zoom, true);
|
const gap = getBgGridGap(zoom);
|
||||||
|
|
||||||
this.background.style.setProperty(
|
this.background.style.setProperty(
|
||||||
'background-position',
|
'background-position',
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { SurfaceBlockModel } from '@blocksuite/affine-block-surface';
|
import type { SurfaceBlockModel } from '@blocksuite/affine-block-surface';
|
||||||
import { Overlay } from '@blocksuite/affine-block-surface';
|
import { Overlay } from '@blocksuite/affine-block-surface';
|
||||||
import type { FrameBlockModel, NoteBlockModel } from '@blocksuite/affine-model';
|
import type { FrameBlockModel } from '@blocksuite/affine-model';
|
||||||
import { EditPropsStore } from '@blocksuite/affine-shared/services';
|
import { EditPropsStore } from '@blocksuite/affine-shared/services';
|
||||||
import {
|
import {
|
||||||
generateKeyBetweenV2,
|
generateKeyBetweenV2,
|
||||||
@@ -21,7 +21,6 @@ import {
|
|||||||
type IVec,
|
type IVec,
|
||||||
type SerializedXYWH,
|
type SerializedXYWH,
|
||||||
} from '@blocksuite/global/utils';
|
} from '@blocksuite/global/utils';
|
||||||
import type { Store } from '@blocksuite/store';
|
|
||||||
import { Text } from '@blocksuite/store';
|
import { Text } from '@blocksuite/store';
|
||||||
import * as Y from 'yjs';
|
import * as Y from 'yjs';
|
||||||
|
|
||||||
@@ -462,47 +461,3 @@ export class EdgelessFrameManager extends GfxExtension {
|
|||||||
this._disposable.dispose();
|
this._disposable.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getNotesInFrameBound(
|
|
||||||
doc: Store,
|
|
||||||
frame: FrameBlockModel,
|
|
||||||
fullyContained: boolean = true
|
|
||||||
) {
|
|
||||||
const bound = Bound.deserialize(frame.xywh);
|
|
||||||
|
|
||||||
return (doc.getBlockByFlavour('affine:note') as NoteBlockModel[]).filter(
|
|
||||||
ele => {
|
|
||||||
const xywh = Bound.deserialize(ele.xywh);
|
|
||||||
|
|
||||||
return fullyContained
|
|
||||||
? bound.contains(xywh)
|
|
||||||
: bound.isPointInBound([xywh.x, xywh.y]);
|
|
||||||
}
|
|
||||||
) as NoteBlockModel[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getBlocksInFrameBound(
|
|
||||||
doc: Store,
|
|
||||||
model: FrameBlockModel,
|
|
||||||
fullyContained: boolean = true
|
|
||||||
) {
|
|
||||||
const bound = Bound.deserialize(model.xywh);
|
|
||||||
const surface = model.surface;
|
|
||||||
if (!surface) return [];
|
|
||||||
|
|
||||||
return (
|
|
||||||
getNotesInFrameBound(doc, model, fullyContained) as GfxBlockElementModel[]
|
|
||||||
).concat(
|
|
||||||
surface.children.filter(ele => {
|
|
||||||
if (ele.id === model.id) return false;
|
|
||||||
if (ele instanceof GfxBlockElementModel) {
|
|
||||||
const blockBound = Bound.deserialize(ele.xywh);
|
|
||||||
return fullyContained
|
|
||||||
? bound.contains(blockBound)
|
|
||||||
: bound.containsPoint([blockBound.x, blockBound.y]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}) as GfxBlockElementModel[]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
import type { GfxBlockElementModel } from '@blocksuite/block-std/gfx';
|
|
||||||
import { deserializeXYWH } from '@blocksuite/global/utils';
|
|
||||||
|
|
||||||
export function xywhArrayToObject(element: GfxBlockElementModel) {
|
|
||||||
const [x, y, w, h] = deserializeXYWH(element.xywh);
|
|
||||||
return { x, y, w, h };
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,4 @@
|
|||||||
import {
|
import type { CanvasElementWithText } from '@blocksuite/affine-block-surface';
|
||||||
type CanvasElementWithText,
|
|
||||||
GRID_GAP_MAX,
|
|
||||||
GRID_GAP_MIN,
|
|
||||||
} from '@blocksuite/affine-block-surface';
|
|
||||||
import {
|
import {
|
||||||
type AttachmentBlockModel,
|
type AttachmentBlockModel,
|
||||||
type BookmarkBlockModel,
|
type BookmarkBlockModel,
|
||||||
@@ -34,7 +30,7 @@ import type {
|
|||||||
Viewport,
|
Viewport,
|
||||||
} from '@blocksuite/block-std/gfx';
|
} from '@blocksuite/block-std/gfx';
|
||||||
import type { PointLocation } from '@blocksuite/global/utils';
|
import type { PointLocation } from '@blocksuite/global/utils';
|
||||||
import { Bound, clamp } from '@blocksuite/global/utils';
|
import { Bound } from '@blocksuite/global/utils';
|
||||||
import type { BlockModel } from '@blocksuite/store';
|
import type { BlockModel } from '@blocksuite/store';
|
||||||
|
|
||||||
import type { Connectable } from '../../../_common/utils/index.js';
|
import type { Connectable } from '../../../_common/utils/index.js';
|
||||||
@@ -228,18 +224,6 @@ export function getCursorMode(edgelessTool: GfxToolsFullOptionValue | null) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getBackgroundGrid(zoom: number, showGrid: boolean) {
|
|
||||||
const step = zoom < 0.5 ? 2 : 1 / (Math.floor(zoom) || 1);
|
|
||||||
const gap = clamp(20 * step * zoom, GRID_GAP_MIN, GRID_GAP_MAX);
|
|
||||||
|
|
||||||
return {
|
|
||||||
gap,
|
|
||||||
grid: showGrid
|
|
||||||
? 'radial-gradient(var(--affine-edgeless-grid-color) 1px, var(--affine-background-primary-color) 1px)'
|
|
||||||
: 'unset',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export type SelectableProps = {
|
export type SelectableProps = {
|
||||||
bound: Bound;
|
bound: Bound;
|
||||||
rotate: number;
|
rotate: number;
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
import type { CanvasRenderer } from '@blocksuite/affine-block-surface';
|
import type { CanvasRenderer } from '@blocksuite/affine-block-surface';
|
||||||
|
import { ExportManager } from '@blocksuite/affine-block-surface';
|
||||||
import type { SurfaceRefBlockComponent } from '@blocksuite/affine-block-surface-ref';
|
import type { SurfaceRefBlockComponent } from '@blocksuite/affine-block-surface-ref';
|
||||||
import { isTopLevelBlock } from '@blocksuite/affine-shared/utils';
|
import { isTopLevelBlock } from '@blocksuite/affine-shared/utils';
|
||||||
import type { EditorHost } from '@blocksuite/block-std';
|
import type { EditorHost } from '@blocksuite/block-std';
|
||||||
import type { GfxModel } from '@blocksuite/block-std/gfx';
|
import {
|
||||||
|
GfxControllerIdentifier,
|
||||||
|
type GfxModel,
|
||||||
|
} from '@blocksuite/block-std/gfx';
|
||||||
import { assertExists, Bound } from '@blocksuite/global/utils';
|
import { assertExists, Bound } from '@blocksuite/global/utils';
|
||||||
|
|
||||||
import { ExportManager } from '../../../_common/export-manager/export-manager.js';
|
|
||||||
|
|
||||||
export const edgelessToBlob = async (
|
export const edgelessToBlob = async (
|
||||||
host: EditorHost,
|
host: EditorHost,
|
||||||
options: {
|
options: {
|
||||||
@@ -19,12 +21,13 @@ export const edgelessToBlob = async (
|
|||||||
const exportManager = host.std.get(ExportManager);
|
const exportManager = host.std.get(ExportManager);
|
||||||
const bound = Bound.deserialize(edgelessElement.xywh);
|
const bound = Bound.deserialize(edgelessElement.xywh);
|
||||||
const isBlock = isTopLevelBlock(edgelessElement);
|
const isBlock = isTopLevelBlock(edgelessElement);
|
||||||
|
const gfx = host.std.get(GfxControllerIdentifier);
|
||||||
|
|
||||||
return exportManager
|
return exportManager
|
||||||
.edgelessToCanvas(
|
.edgelessToCanvas(
|
||||||
options.surfaceRenderer,
|
options.surfaceRenderer,
|
||||||
bound,
|
bound,
|
||||||
undefined,
|
gfx,
|
||||||
isBlock ? [edgelessElement] : undefined,
|
isBlock ? [edgelessElement] : undefined,
|
||||||
isBlock ? undefined : [edgelessElement],
|
isBlock ? undefined : [edgelessElement],
|
||||||
{ zoom: options.surfaceRenderer.viewport.zoom }
|
{ zoom: options.surfaceRenderer.viewport.zoom }
|
||||||
|
|||||||
@@ -3645,9 +3645,11 @@ __metadata:
|
|||||||
"@toeverything/theme": "npm:^1.1.7"
|
"@toeverything/theme": "npm:^1.1.7"
|
||||||
"@types/lodash.chunk": "npm:^4.2.9"
|
"@types/lodash.chunk": "npm:^4.2.9"
|
||||||
fractional-indexing: "npm:^3.2.0"
|
fractional-indexing: "npm:^3.2.0"
|
||||||
|
html2canvas: "npm:^1.4.1"
|
||||||
lit: "npm:^3.2.0"
|
lit: "npm:^3.2.0"
|
||||||
lodash.chunk: "npm:^4.2.0"
|
lodash.chunk: "npm:^4.2.0"
|
||||||
nanoid: "npm:^5.0.7"
|
nanoid: "npm:^5.0.7"
|
||||||
|
pdf-lib: "npm:^1.17.1"
|
||||||
vitest: "npm:3.0.5"
|
vitest: "npm:3.0.5"
|
||||||
yjs: "npm:^13.6.21"
|
yjs: "npm:^13.6.21"
|
||||||
zod: "npm:^3.23.8"
|
zod: "npm:^3.23.8"
|
||||||
@@ -3958,7 +3960,6 @@ __metadata:
|
|||||||
lz-string: "npm:^1.5.0"
|
lz-string: "npm:^1.5.0"
|
||||||
minimatch: "npm:^10.0.1"
|
minimatch: "npm:^10.0.1"
|
||||||
nanoid: "npm:^5.0.7"
|
nanoid: "npm:^5.0.7"
|
||||||
pdf-lib: "npm:^1.17.1"
|
|
||||||
shiki: "npm:^2.0.0"
|
shiki: "npm:^2.0.0"
|
||||||
simple-xml-to-json: "npm:^1.2.2"
|
simple-xml-to-json: "npm:^1.2.2"
|
||||||
vitest: "npm:3.0.5"
|
vitest: "npm:3.0.5"
|
||||||
|
|||||||
Reference in New Issue
Block a user