mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 04:18:54 +00:00
fix: mini mindmap layout (#9276)
Fixes [BS-2197](https://linear.app/affine-design/issue/BS-2197/ai-生成-mindmap-预览异常)
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
|
// oxlint-disable-next-line @typescript-eslint/triple-slash-reference
|
||||||
/// <reference path="./effects.ts" />
|
/// <reference path="./effects.ts" />
|
||||||
export { type IModelCoord, ZOOM_MAX, ZOOM_MIN, ZOOM_STEP } from './consts.js';
|
export { type IModelCoord, ZOOM_MAX, ZOOM_MIN, ZOOM_STEP } from './consts.js';
|
||||||
export { GRID_GAP_MAX, GRID_GAP_MIN } from './consts.js';
|
export { GRID_GAP_MAX, GRID_GAP_MIN } from './consts.js';
|
||||||
@@ -29,6 +29,7 @@ export {
|
|||||||
export { fitContent } from './renderer/elements/shape/utils.js';
|
export { fitContent } from './renderer/elements/shape/utils.js';
|
||||||
export * from './renderer/elements/type.js';
|
export * from './renderer/elements/type.js';
|
||||||
export { Overlay, OverlayIdentifier } from './renderer/overlay.js';
|
export { Overlay, OverlayIdentifier } from './renderer/overlay.js';
|
||||||
|
export { MindMapView } from './view/mindmap.js';
|
||||||
import {
|
import {
|
||||||
getCursorByCoord,
|
getCursorByCoord,
|
||||||
getLineHeight,
|
getLineHeight,
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
import { SurfaceBlockSchema } from '@blocksuite/affine-block-surface';
|
import {
|
||||||
|
MindMapView,
|
||||||
|
SurfaceBlockSchema,
|
||||||
|
} from '@blocksuite/affine-block-surface';
|
||||||
import { RootBlockSchema } from '@blocksuite/affine-model';
|
import { RootBlockSchema } from '@blocksuite/affine-model';
|
||||||
import {
|
import {
|
||||||
DocModeService,
|
DocModeService,
|
||||||
@@ -23,6 +26,7 @@ export const MiniMindmapSpecs: ExtensionType[] = [
|
|||||||
MindmapService,
|
MindmapService,
|
||||||
BlockViewExtension('affine:page', literal`mini-mindmap-root-block`),
|
BlockViewExtension('affine:page', literal`mini-mindmap-root-block`),
|
||||||
FlavourExtension('affine:surface'),
|
FlavourExtension('affine:surface'),
|
||||||
|
MindMapView,
|
||||||
MindmapSurfaceBlockService,
|
MindmapSurfaceBlockService,
|
||||||
BlockViewExtension('affine:surface', literal`mini-mindmap-surface-block`),
|
BlockViewExtension('affine:surface', literal`mini-mindmap-surface-block`),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -12,9 +12,26 @@ import { wait } from '../utils/common.js';
|
|||||||
import { getDocRootBlock } from '../utils/edgeless.js';
|
import { getDocRootBlock } from '../utils/edgeless.js';
|
||||||
import { setupEditor } from '../utils/setup.js';
|
import { setupEditor } from '../utils/setup.js';
|
||||||
|
|
||||||
describe('mind map', () => {
|
describe('mini mindmap preview', () => {
|
||||||
let edgeless!: EdgelessRootBlockComponent;
|
let edgeless!: EdgelessRootBlockComponent;
|
||||||
|
|
||||||
|
const createPreview = (host: EditorHost, answer: string) => {
|
||||||
|
const mindmapPreview = new MiniMindmapPreview();
|
||||||
|
|
||||||
|
mindmapPreview.answer = answer;
|
||||||
|
mindmapPreview.host = host;
|
||||||
|
mindmapPreview.ctx = {
|
||||||
|
get() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
set() {},
|
||||||
|
};
|
||||||
|
|
||||||
|
document.body.append(mindmapPreview);
|
||||||
|
|
||||||
|
return mindmapPreview;
|
||||||
|
};
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const cleanup = await setupEditor('edgeless');
|
const cleanup = await setupEditor('edgeless');
|
||||||
|
|
||||||
@@ -25,7 +42,7 @@ describe('mind map', () => {
|
|||||||
return cleanup;
|
return cleanup;
|
||||||
});
|
});
|
||||||
|
|
||||||
test('mind map preview', async () => {
|
test('mini mindmap basic', async () => {
|
||||||
const mindmapAnswer = `
|
const mindmapAnswer = `
|
||||||
- Mindmap
|
- Mindmap
|
||||||
- Node 1
|
- Node 1
|
||||||
@@ -36,74 +53,65 @@ describe('mind map', () => {
|
|||||||
- Node 2.2
|
- Node 2.2
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const createPreview = (
|
const miniMindMapPreview = createPreview(
|
||||||
host: EditorHost,
|
window.editor.host!,
|
||||||
answer: string = mindmapAnswer
|
mindmapAnswer
|
||||||
) => {
|
);
|
||||||
const mindmapPreview = new MiniMindmapPreview();
|
|
||||||
|
|
||||||
mindmapPreview.answer = answer;
|
|
||||||
mindmapPreview.host = host;
|
|
||||||
mindmapPreview.ctx = {
|
|
||||||
get() {
|
|
||||||
return {};
|
|
||||||
},
|
|
||||||
set() {},
|
|
||||||
};
|
|
||||||
|
|
||||||
document.body.append(mindmapPreview);
|
|
||||||
|
|
||||||
return mindmapPreview;
|
|
||||||
};
|
|
||||||
|
|
||||||
const miniMindMapPreview = createPreview(window.editor.host!);
|
|
||||||
await wait(50);
|
await wait(50);
|
||||||
const miniMindMapSurface = miniMindMapPreview.renderRoot.querySelector(
|
const miniMindMapSurface = miniMindMapPreview.renderRoot.querySelector(
|
||||||
'mini-mindmap-surface-block'
|
'mini-mindmap-surface-block'
|
||||||
) as MindmapSurfaceBlock;
|
) as MindmapSurfaceBlock;
|
||||||
|
|
||||||
expect(miniMindMapSurface).not.toBeNull();
|
// model-related properties
|
||||||
|
expect(miniMindMapPreview.mindmapId).toBeDefined();
|
||||||
|
expect(miniMindMapPreview.portalHost).toBeDefined();
|
||||||
|
expect(miniMindMapPreview.doc).toBeDefined();
|
||||||
|
expect(miniMindMapPreview.surface).toBeDefined();
|
||||||
|
expect(miniMindMapPreview.surface!.elementModels.length).toBe(8);
|
||||||
|
|
||||||
|
// renderer
|
||||||
expect(miniMindMapSurface.renderer).toBeDefined();
|
expect(miniMindMapSurface.renderer).toBeDefined();
|
||||||
expect(miniMindMapSurface.renderer?.canvas.isConnected).toBe(true);
|
expect(miniMindMapSurface.renderer?.canvas.isConnected).toBe(true);
|
||||||
expect(miniMindMapSurface.renderer?.canvas.width).toBeGreaterThan(0);
|
expect(miniMindMapSurface.renderer?.canvas.width).toBeGreaterThan(0);
|
||||||
expect(miniMindMapSurface.renderer?.canvas.height).toBeGreaterThan(0);
|
expect(miniMindMapSurface.renderer?.canvas.height).toBeGreaterThan(0);
|
||||||
|
|
||||||
expect(miniMindMapSurface.model.elementModels.length).toBe(8);
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
miniMindMapPreview.remove();
|
miniMindMapPreview.remove();
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
test('new mind map should layout automatically', async () => {
|
test('mini mindmap should layout automatically', async () => {
|
||||||
const gfx = editor.std.get(GfxControllerIdentifier);
|
const mindmapAnswer = `
|
||||||
const mindmapId = gfx.surface!.addElement({
|
- Main node
|
||||||
type: 'mindmap',
|
- Child node
|
||||||
children: {
|
- Second child node
|
||||||
text: 'Main node',
|
- Third child node
|
||||||
children: [
|
`;
|
||||||
{
|
|
||||||
text: 'Child node',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Second child node',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Third child node',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const mindmap = gfx.getElementById(mindmapId) as MindmapElementModel;
|
|
||||||
await wait(0);
|
|
||||||
const [child1, child2, child3] = mindmap.tree.children;
|
|
||||||
|
|
||||||
expect(mindmapId).not.toBeUndefined();
|
const miniMindMapPreview = createPreview(
|
||||||
expect(mindmap.tree.children.length).toBe(3);
|
window.editor.host!,
|
||||||
expect(mindmap.tree.element.x).toBeLessThan(child1.element.x);
|
mindmapAnswer
|
||||||
|
);
|
||||||
|
|
||||||
|
await wait(50);
|
||||||
|
const gfx = miniMindMapPreview.portalHost.std.get(GfxControllerIdentifier);
|
||||||
|
const mindmap = gfx.surface!.elementModels.filter(
|
||||||
|
model => model.type === 'mindmap'
|
||||||
|
)[0] as MindmapElementModel;
|
||||||
|
const [child1, child2, child3] = mindmap.tree.children;
|
||||||
|
const root = mindmap.tree;
|
||||||
|
|
||||||
|
expect(mindmap).not.toBeUndefined();
|
||||||
|
|
||||||
|
expect(root.children.length).toBe(3);
|
||||||
|
expect(root.element.x).toBeLessThan(child1.element.x);
|
||||||
|
|
||||||
|
// children should be aligned horizontally
|
||||||
expect(child1.element.x).toBe(child2.element.x);
|
expect(child1.element.x).toBe(child2.element.x);
|
||||||
expect(child2.element.x).toBe(child3.element.x);
|
expect(child2.element.x).toBe(child3.element.x);
|
||||||
expect(child1.element.y).toBeLessThan(child2.element.y);
|
|
||||||
expect(child2.element.y).toBeLessThan(child3.element.y);
|
// children
|
||||||
|
expect(child1.element.y + child1.element.h).toBeLessThan(child2.element.y);
|
||||||
|
expect(child2.element.y + child2.element.h).toBeLessThan(child3.element.y);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user