chore(editor): adjust size of synced doc (#12163)
Close [BS-3418](https://linear.app/affine-design/issue/BS-3418/折叠的embed-doc调整宽度时,会出现一个最小高度,不需要这个) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Improved resizing and folding interactions for embedded synced documents in edgeless mode, including dynamic height calculation and enhanced drag-handle styling. - **Bug Fixes** - Adjusted minimum height for synced document embeds to allow more compact display. - Ensured consistent width settings across embed cards. - **Tests** - Added end-to-end tests covering folding, unfolding, and resizing behaviors for edgeless synced document embeds. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -0,0 +1,85 @@
|
|||||||
|
import {
|
||||||
|
EmbedSyncedDocBlockSchema,
|
||||||
|
SYNCED_MIN_HEIGHT,
|
||||||
|
SYNCED_MIN_WIDTH,
|
||||||
|
} from '@blocksuite/affine-model';
|
||||||
|
import { clamp } from '@blocksuite/global/gfx';
|
||||||
|
import { GfxViewInteractionExtension } from '@blocksuite/std/gfx';
|
||||||
|
|
||||||
|
import type { EmbedEdgelessSyncedDocBlockComponent } from '../embed-edgeless-synced-doc-block';
|
||||||
|
import { calcSyncedDocFullHeight } from '../utils';
|
||||||
|
|
||||||
|
export const EmbedSyncedDocInteraction =
|
||||||
|
GfxViewInteractionExtension<EmbedEdgelessSyncedDocBlockComponent>(
|
||||||
|
EmbedSyncedDocBlockSchema.model.flavour,
|
||||||
|
{
|
||||||
|
resizeConstraint: {
|
||||||
|
minWidth: SYNCED_MIN_WIDTH,
|
||||||
|
minHeight: SYNCED_MIN_HEIGHT,
|
||||||
|
},
|
||||||
|
|
||||||
|
handleRotate: () => {
|
||||||
|
return {
|
||||||
|
beforeRotate(context) {
|
||||||
|
context.set({
|
||||||
|
rotatable: false,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
handleResize: ({ view, model }) => {
|
||||||
|
const initialScale = model.props.scale ?? 1;
|
||||||
|
const initHeight = model.elementBound.h;
|
||||||
|
const maxHeight = calcSyncedDocFullHeight(view);
|
||||||
|
|
||||||
|
return {
|
||||||
|
beforeResize: context => {
|
||||||
|
context.set({ maxHeight });
|
||||||
|
},
|
||||||
|
onResizeStart: context => {
|
||||||
|
context.default(context);
|
||||||
|
model.stash('scale');
|
||||||
|
model.stash('preFoldHeight');
|
||||||
|
},
|
||||||
|
onResizeMove: context => {
|
||||||
|
const { lockRatio, originalBound, constraint, newBound } = context;
|
||||||
|
|
||||||
|
let scale = initialScale;
|
||||||
|
const realWidth = originalBound.w / initialScale;
|
||||||
|
|
||||||
|
if (lockRatio) {
|
||||||
|
scale = newBound.w / realWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newWidth = newBound.w / scale;
|
||||||
|
|
||||||
|
newBound.w =
|
||||||
|
clamp(newWidth, constraint.minWidth, constraint.maxWidth) * scale;
|
||||||
|
newBound.h =
|
||||||
|
clamp(newBound.h, constraint.minHeight, constraint.maxHeight) *
|
||||||
|
scale;
|
||||||
|
|
||||||
|
const newHeight = newBound.h / scale;
|
||||||
|
|
||||||
|
// only adjust height check the fold state
|
||||||
|
if (originalBound.w === newBound.w) {
|
||||||
|
let preFoldHeight = 0;
|
||||||
|
if (newHeight === constraint.minHeight) {
|
||||||
|
preFoldHeight = initHeight;
|
||||||
|
}
|
||||||
|
model.props.preFoldHeight = preFoldHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
model.props.scale = scale;
|
||||||
|
model.xywh = newBound.serialize();
|
||||||
|
},
|
||||||
|
onResizeEnd: context => {
|
||||||
|
context.default(context);
|
||||||
|
model.pop('scale');
|
||||||
|
model.pop('preFoldHeight');
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
@@ -3,12 +3,7 @@ import {
|
|||||||
EdgelessCRUDIdentifier,
|
EdgelessCRUDIdentifier,
|
||||||
reassociateConnectorsCommand,
|
reassociateConnectorsCommand,
|
||||||
} from '@blocksuite/affine-block-surface';
|
} from '@blocksuite/affine-block-surface';
|
||||||
import {
|
import { type AliasInfo } from '@blocksuite/affine-model';
|
||||||
type AliasInfo,
|
|
||||||
EmbedSyncedDocBlockSchema,
|
|
||||||
SYNCED_MIN_HEIGHT,
|
|
||||||
SYNCED_MIN_WIDTH,
|
|
||||||
} from '@blocksuite/affine-model';
|
|
||||||
import {
|
import {
|
||||||
EMBED_CARD_HEIGHT,
|
EMBED_CARD_HEIGHT,
|
||||||
EMBED_CARD_WIDTH,
|
EMBED_CARD_WIDTH,
|
||||||
@@ -17,11 +12,10 @@ import {
|
|||||||
ThemeExtensionIdentifier,
|
ThemeExtensionIdentifier,
|
||||||
ThemeProvider,
|
ThemeProvider,
|
||||||
} from '@blocksuite/affine-shared/services';
|
} from '@blocksuite/affine-shared/services';
|
||||||
import { Bound, clamp } from '@blocksuite/global/gfx';
|
import { Bound } from '@blocksuite/global/gfx';
|
||||||
import { type BlockComponent, BlockStdScope } from '@blocksuite/std';
|
import { type BlockComponent, BlockStdScope } from '@blocksuite/std';
|
||||||
import { GfxViewInteractionExtension } from '@blocksuite/std/gfx';
|
|
||||||
import { html, nothing } from 'lit';
|
import { html, nothing } from 'lit';
|
||||||
import { query, queryAsync } from 'lit/decorators.js';
|
import { query } from 'lit/decorators.js';
|
||||||
import { choose } from 'lit/directives/choose.js';
|
import { choose } from 'lit/directives/choose.js';
|
||||||
import { classMap } from 'lit/directives/class-map.js';
|
import { classMap } from 'lit/directives/class-map.js';
|
||||||
import { guard } from 'lit/directives/guard.js';
|
import { guard } from 'lit/directives/guard.js';
|
||||||
@@ -37,8 +31,8 @@ export class EmbedEdgelessSyncedDocBlockComponent extends toEdgelessEmbedBlock(
|
|||||||
@query('.affine-embed-synced-doc-edgeless-header-wrapper')
|
@query('.affine-embed-synced-doc-edgeless-header-wrapper')
|
||||||
accessor headerWrapper: HTMLDivElement | null = null;
|
accessor headerWrapper: HTMLDivElement | null = null;
|
||||||
|
|
||||||
@queryAsync('affine-preview-root')
|
@query('affine-preview-root')
|
||||||
accessor contentElement!: Promise<BlockComponent | null>;
|
accessor contentElement: BlockComponent | null = null;
|
||||||
|
|
||||||
protected override _renderSyncedView = () => {
|
protected override _renderSyncedView = () => {
|
||||||
const { syncedDoc, editorMode } = this;
|
const { syncedDoc, editorMode } = this;
|
||||||
@@ -205,60 +199,3 @@ export class EmbedEdgelessSyncedDocBlockComponent extends toEdgelessEmbedBlock(
|
|||||||
|
|
||||||
override accessor useCaptionEditor = true;
|
override accessor useCaptionEditor = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const EmbedSyncedDocInteraction =
|
|
||||||
GfxViewInteractionExtension<EmbedEdgelessSyncedDocBlockComponent>(
|
|
||||||
EmbedSyncedDocBlockSchema.model.flavour,
|
|
||||||
{
|
|
||||||
resizeConstraint: {
|
|
||||||
minWidth: SYNCED_MIN_WIDTH,
|
|
||||||
minHeight: SYNCED_MIN_HEIGHT,
|
|
||||||
},
|
|
||||||
|
|
||||||
handleRotate: () => {
|
|
||||||
return {
|
|
||||||
beforeRotate(context) {
|
|
||||||
context.set({
|
|
||||||
rotatable: false,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
handleResize: ({ model }) => {
|
|
||||||
const initialScale = model.props.scale ?? 1;
|
|
||||||
|
|
||||||
return {
|
|
||||||
onResizeStart: context => {
|
|
||||||
context.default(context);
|
|
||||||
model.stash('scale');
|
|
||||||
},
|
|
||||||
onResizeMove: context => {
|
|
||||||
const { lockRatio, originalBound, constraint, newBound } = context;
|
|
||||||
|
|
||||||
let scale = initialScale;
|
|
||||||
const realWidth = originalBound.w / initialScale;
|
|
||||||
|
|
||||||
if (lockRatio) {
|
|
||||||
scale = newBound.w / realWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newWidth = newBound.w / scale;
|
|
||||||
|
|
||||||
newBound.w =
|
|
||||||
clamp(newWidth, constraint.minWidth, constraint.maxWidth) * scale;
|
|
||||||
newBound.h =
|
|
||||||
clamp(newBound.h, constraint.minHeight, constraint.maxHeight) *
|
|
||||||
scale;
|
|
||||||
|
|
||||||
model.props.scale = scale;
|
|
||||||
model.xywh = newBound.serialize();
|
|
||||||
},
|
|
||||||
onResizeEnd: context => {
|
|
||||||
context.default(context);
|
|
||||||
model.pop('scale');
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import { literal } from 'lit/static-html.js';
|
|||||||
|
|
||||||
import { EmbedSyncedDocBlockAdapterExtensions } from './adapters/extension';
|
import { EmbedSyncedDocBlockAdapterExtensions } from './adapters/extension';
|
||||||
import { createBuiltinToolbarConfigExtension } from './configs/toolbar';
|
import { createBuiltinToolbarConfigExtension } from './configs/toolbar';
|
||||||
import { EmbedSyncedDocInteraction } from './embed-edgeless-synced-doc-block';
|
|
||||||
import { HeightInitializationExtension } from './init-height-extension';
|
import { HeightInitializationExtension } from './init-height-extension';
|
||||||
|
|
||||||
const flavour = EmbedSyncedDocBlockSchema.model.flavour;
|
const flavour = EmbedSyncedDocBlockSchema.model.flavour;
|
||||||
@@ -30,5 +29,4 @@ export const EmbedSyncedDocViewExtensions: ExtensionType[] = [
|
|||||||
}),
|
}),
|
||||||
createBuiltinToolbarConfigExtension(flavour),
|
createBuiltinToolbarConfigExtension(flavour),
|
||||||
HeightInitializationExtension,
|
HeightInitializationExtension,
|
||||||
EmbedSyncedDocInteraction,
|
|
||||||
].flat();
|
].flat();
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
import {
|
import { EmbedSyncedDocBlockSchema } from '@blocksuite/affine-model';
|
||||||
EmbedSyncedDocBlockSchema,
|
|
||||||
SYNCED_DEFAULT_MAX_HEIGHT,
|
|
||||||
SYNCED_MIN_HEIGHT,
|
|
||||||
} from '@blocksuite/affine-model';
|
|
||||||
import { DisposableGroup } from '@blocksuite/global/disposable';
|
import { DisposableGroup } from '@blocksuite/global/disposable';
|
||||||
import { clamp } from '@blocksuite/global/gfx';
|
|
||||||
import { LifeCycleWatcher } from '@blocksuite/std';
|
import { LifeCycleWatcher } from '@blocksuite/std';
|
||||||
|
|
||||||
import { EmbedEdgelessSyncedDocBlockComponent } from './embed-edgeless-synced-doc-block';
|
import { EmbedEdgelessSyncedDocBlockComponent } from './embed-edgeless-synced-doc-block';
|
||||||
|
import { calcSyncedDocFullHeight } from './utils';
|
||||||
|
|
||||||
export class HeightInitializationExtension extends LifeCycleWatcher {
|
export class HeightInitializationExtension extends LifeCycleWatcher {
|
||||||
static override key = 'embed-synced-doc-block-height-initialization';
|
static override key = 'embed-synced-doc-block-height-initialization';
|
||||||
@@ -41,26 +37,17 @@ export class HeightInitializationExtension extends LifeCycleWatcher {
|
|||||||
}
|
}
|
||||||
const block = payload.view;
|
const block = payload.view;
|
||||||
|
|
||||||
block.contentElement
|
block.updateComplete
|
||||||
.then(contentEl => {
|
.then(() => {
|
||||||
if (!contentEl) return;
|
if (!block.contentElement) return;
|
||||||
|
|
||||||
const resizeObserver = new ResizeObserver(() => {
|
const resizeObserver = new ResizeObserver(() => {
|
||||||
const headerHeight =
|
|
||||||
block.headerWrapper?.getBoundingClientRect().height ?? 0;
|
|
||||||
const contentHeight = contentEl.getBoundingClientRect().height;
|
|
||||||
|
|
||||||
const { x, y, w } = block.model.elementBound;
|
const { x, y, w } = block.model.elementBound;
|
||||||
const h = clamp(
|
const h = calcSyncedDocFullHeight(block);
|
||||||
(headerHeight + contentHeight) / block.gfx.viewport.zoom,
|
|
||||||
SYNCED_MIN_HEIGHT,
|
|
||||||
SYNCED_DEFAULT_MAX_HEIGHT
|
|
||||||
);
|
|
||||||
block.model.xywh$.value = `[${x},${y},${w},${h}]`;
|
block.model.xywh$.value = `[${x},${y},${w},${h}]`;
|
||||||
|
|
||||||
resizeObserver.unobserve(contentEl);
|
resizeObserver.disconnect();
|
||||||
});
|
});
|
||||||
resizeObserver.observe(contentEl);
|
resizeObserver.observe(block.contentElement);
|
||||||
})
|
})
|
||||||
.catch(console.error);
|
.catch(console.error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ import {
|
|||||||
ReloadIcon,
|
ReloadIcon,
|
||||||
} from '@blocksuite/affine-components/icons';
|
} from '@blocksuite/affine-components/icons';
|
||||||
import { ColorScheme } from '@blocksuite/affine-model';
|
import { ColorScheme } from '@blocksuite/affine-model';
|
||||||
|
import type { BlockComponent } from '@blocksuite/std';
|
||||||
import type { TemplateResult } from 'lit';
|
import type { TemplateResult } from 'lit';
|
||||||
|
|
||||||
|
import { EmbedEdgelessSyncedDocBlockComponent } from './embed-edgeless-synced-doc-block.js';
|
||||||
import {
|
import {
|
||||||
DarkSyncedDocDeletedBanner,
|
DarkSyncedDocDeletedBanner,
|
||||||
DarkSyncedDocEmptyBanner,
|
DarkSyncedDocEmptyBanner,
|
||||||
@@ -58,3 +60,22 @@ export function getSyncedDocIcons(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function will return the height of the synced doc block
|
||||||
|
*/
|
||||||
|
export function calcSyncedDocFullHeight(block: BlockComponent) {
|
||||||
|
if (!(block instanceof EmbedEdgelessSyncedDocBlockComponent)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const headerHeight = block.headerWrapper?.getBoundingClientRect().height ?? 0;
|
||||||
|
// When the content is not found, we use a default height to display empty information
|
||||||
|
const contentHeight =
|
||||||
|
block.contentElement?.getBoundingClientRect().height ?? 200;
|
||||||
|
|
||||||
|
const bottomPadding = 8;
|
||||||
|
|
||||||
|
return (
|
||||||
|
(headerHeight + contentHeight + bottomPadding) / block.gfx.viewport.zoom
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ import {
|
|||||||
} from './embed-linked-doc-block';
|
} from './embed-linked-doc-block';
|
||||||
import {
|
import {
|
||||||
EdgelessClipboardEmbedSyncedDocConfig,
|
EdgelessClipboardEmbedSyncedDocConfig,
|
||||||
EmbedSyncedDocInteraction,
|
|
||||||
EmbedSyncedDocViewExtensions,
|
EmbedSyncedDocViewExtensions,
|
||||||
} from './embed-synced-doc-block';
|
} from './embed-synced-doc-block';
|
||||||
|
import { EmbedSyncedDocInteraction } from './embed-synced-doc-block/configs/edgeless-interaction';
|
||||||
|
|
||||||
export class EmbedDocViewExtension extends ViewExtensionProvider {
|
export class EmbedDocViewExtension extends ViewExtensionProvider {
|
||||||
override name = 'affine-embed-doc-block';
|
override name = 'affine-embed-doc-block';
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ import {
|
|||||||
} from './synced-doc-model.js';
|
} from './synced-doc-model.js';
|
||||||
|
|
||||||
export const SYNCED_MIN_WIDTH = 370;
|
export const SYNCED_MIN_WIDTH = 370;
|
||||||
export const SYNCED_MIN_HEIGHT = 64;
|
export const SYNCED_MIN_HEIGHT = 48;
|
||||||
|
export const SYNCED_DEFAULT_WIDTH = 800;
|
||||||
// the default max height of embed doc, user can adjust height by selected rect over this value
|
// the default max height of embed doc, user can adjust height by selected rect over this value
|
||||||
export const SYNCED_DEFAULT_MAX_HEIGHT = 800;
|
export const SYNCED_DEFAULT_MAX_HEIGHT = 800;
|
||||||
|
|
||||||
@@ -22,7 +23,7 @@ export const defaultEmbedSyncedDocBlockProps: EmbedSyncedDocBlockProps = {
|
|||||||
title: undefined,
|
title: undefined,
|
||||||
description: undefined,
|
description: undefined,
|
||||||
index: 'a0',
|
index: 'a0',
|
||||||
xywh: `[0,0,${SYNCED_MIN_WIDTH},100]`,
|
xywh: `[0,0,${SYNCED_DEFAULT_WIDTH},100]`,
|
||||||
lockedBySelf: undefined,
|
lockedBySelf: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
EmbedLoomModel,
|
EmbedLoomModel,
|
||||||
EmbedSyncedDocModel,
|
EmbedSyncedDocModel,
|
||||||
EmbedYoutubeModel,
|
EmbedYoutubeModel,
|
||||||
|
SYNCED_DEFAULT_WIDTH,
|
||||||
} from '@blocksuite/affine-model';
|
} from '@blocksuite/affine-model';
|
||||||
|
|
||||||
export const BLOCK_CHILDREN_CONTAINER_PADDING_LEFT = 24;
|
export const BLOCK_CHILDREN_CONTAINER_PADDING_LEFT = 24;
|
||||||
@@ -29,7 +30,7 @@ export const EMBED_CARD_WIDTH: Record<EmbedCardStyle, number> = {
|
|||||||
video: 752,
|
video: 752,
|
||||||
figma: 752,
|
figma: 752,
|
||||||
html: 752,
|
html: 752,
|
||||||
syncedDoc: 800,
|
syncedDoc: SYNCED_DEFAULT_WIDTH,
|
||||||
pdf: 537 + 24 + 2,
|
pdf: 537 + 24 + 2,
|
||||||
citation: 752,
|
citation: 752,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ export class DNDAPIExtension extends Extension {
|
|||||||
...options.props,
|
...options.props,
|
||||||
...(blockId ? { blockId } : {}),
|
...(blockId ? { blockId } : {}),
|
||||||
pageId: docId,
|
pageId: docId,
|
||||||
|
style: flavour === 'affine:embed-synced-doc' ? 'syncedDoc' : 'vertical',
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
...snapshot,
|
...snapshot,
|
||||||
|
|||||||
@@ -1089,7 +1089,7 @@ export class DragEventWatcher {
|
|||||||
block.flavour === 'affine:bookmark' ||
|
block.flavour === 'affine:bookmark' ||
|
||||||
block.flavour.startsWith('affine:embed-')
|
block.flavour.startsWith('affine:embed-')
|
||||||
) {
|
) {
|
||||||
const style = 'vertical' as EmbedCardStyle;
|
const style = (block.props.style ?? 'vertical') as EmbedCardStyle;
|
||||||
block.props.style = style;
|
block.props.style = style;
|
||||||
|
|
||||||
blockBound.w = EMBED_CARD_WIDTH[style];
|
blockBound.w = EMBED_CARD_WIDTH[style];
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ import { stopPropagation } from '@affine/core/utils';
|
|||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
import { EmbedSyncedDocBlockComponent } from '@blocksuite/affine/blocks/embed-doc';
|
import { EmbedSyncedDocBlockComponent } from '@blocksuite/affine/blocks/embed-doc';
|
||||||
import { isPeekable, peek } from '@blocksuite/affine/components/peek';
|
import { isPeekable, peek } from '@blocksuite/affine/components/peek';
|
||||||
import { DisposableGroup } from '@blocksuite/affine/global/disposable';
|
|
||||||
import { Bound } from '@blocksuite/affine/global/gfx';
|
|
||||||
import type { EmbedSyncedDocModel } from '@blocksuite/affine-model';
|
import type { EmbedSyncedDocModel } from '@blocksuite/affine-model';
|
||||||
import {
|
import {
|
||||||
ArrowDownSmallIcon,
|
ArrowDownSmallIcon,
|
||||||
@@ -30,28 +28,10 @@ const ToggleButton = ({ model }: { model: EmbedSyncedDocModel }) => {
|
|||||||
const [isFolded, setIsFolded] = useState(model.isFolded);
|
const [isFolded, setIsFolded] = useState(model.isFolded);
|
||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(
|
||||||
const disposables = new DisposableGroup();
|
() => model.props.preFoldHeight$.subscribe(value => setIsFolded(!!value)),
|
||||||
disposables.add(
|
[model.props.preFoldHeight$]
|
||||||
model.props.preFoldHeight$.subscribe(value => setIsFolded(!!value))
|
|
||||||
);
|
);
|
||||||
// the height may be changed by dragging selected rect
|
|
||||||
disposables.add(
|
|
||||||
model.xywh$.subscribe(value => {
|
|
||||||
const bound = Bound.deserialize(value);
|
|
||||||
const preFoldHeight = model.props.preFoldHeight$.peek();
|
|
||||||
if (
|
|
||||||
bound.h !== styles.headerHeight &&
|
|
||||||
preFoldHeight !== undefined &&
|
|
||||||
bound.h !== preFoldHeight
|
|
||||||
) {
|
|
||||||
model.props.preFoldHeight$.value = 0;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
return () => disposables.dispose();
|
|
||||||
}, [model.props.preFoldHeight$, model.xywh$]);
|
|
||||||
|
|
||||||
const toggle = useCallback(() => {
|
const toggle = useCallback(() => {
|
||||||
model.store.captureSync();
|
model.store.captureSync();
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import {
|
|||||||
clickView,
|
clickView,
|
||||||
createEdgelessNoteBlock,
|
createEdgelessNoteBlock,
|
||||||
fitViewportToContent,
|
fitViewportToContent,
|
||||||
|
getSelectedXYWH,
|
||||||
locateEditorContainer,
|
locateEditorContainer,
|
||||||
|
resizeElementByHandle,
|
||||||
} from '@affine-test/kit/utils/editor';
|
} from '@affine-test/kit/utils/editor';
|
||||||
import { pressEnter } from '@affine-test/kit/utils/keyboard';
|
import { pressEnter } from '@affine-test/kit/utils/keyboard';
|
||||||
import { openHomePage } from '@affine-test/kit/utils/load-page';
|
import { openHomePage } from '@affine-test/kit/utils/load-page';
|
||||||
@@ -72,6 +74,7 @@ test.describe('edgeless', () => {
|
|||||||
.getByTestId('cmdk-quick-search')
|
.getByTestId('cmdk-quick-search')
|
||||||
.getByText(/^Synced Block Test$/)
|
.getByText(/^Synced Block Test$/)
|
||||||
.click();
|
.click();
|
||||||
|
|
||||||
await fitViewportToContent(page);
|
await fitViewportToContent(page);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -100,4 +103,61 @@ test.describe('edgeless', () => {
|
|||||||
await expect(headerTitle).toHaveText(title);
|
await expect(headerTitle).toHaveText(title);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test.describe('size adjustment of embed synced doc', () => {
|
||||||
|
test('should fold embed synced doc when adjust height to smallest', async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
const [, , , h] = await getSelectedXYWH(page);
|
||||||
|
await resizeElementByHandle(page, [0, -(h - 10)], 'bottom-right');
|
||||||
|
|
||||||
|
const embedBlock = page.locator('affine-embed-edgeless-synced-doc-block');
|
||||||
|
const foldButton = embedBlock.getByTestId(
|
||||||
|
'edgeless-embed-synced-doc-fold-button'
|
||||||
|
);
|
||||||
|
const content = embedBlock.locator('editor-host');
|
||||||
|
|
||||||
|
await expect(foldButton).toHaveAttribute('data-folded', 'true');
|
||||||
|
await expect(content).toBeHidden();
|
||||||
|
|
||||||
|
await foldButton.click();
|
||||||
|
await expect(foldButton).toHaveAttribute('data-folded', 'false');
|
||||||
|
await expect(content).toBeVisible();
|
||||||
|
|
||||||
|
await embedBlock.click();
|
||||||
|
const [, , , h2] = await getSelectedXYWH(page);
|
||||||
|
expect(
|
||||||
|
h2,
|
||||||
|
'should recover height when unfold embed synced doc which was resized to smallest height directly'
|
||||||
|
).toEqual(h);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should be able to adjust height the folded embed synced doc', async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
const embedBlock = page.locator('affine-embed-edgeless-synced-doc-block');
|
||||||
|
|
||||||
|
const content = embedBlock.locator('editor-host');
|
||||||
|
const foldButton = embedBlock.getByTestId(
|
||||||
|
'edgeless-embed-synced-doc-fold-button'
|
||||||
|
);
|
||||||
|
await foldButton.click();
|
||||||
|
|
||||||
|
await resizeElementByHandle(page, [50, 0], 'bottom-right');
|
||||||
|
await expect(content).toBeHidden();
|
||||||
|
await expect(foldButton).toHaveAttribute('data-folded', 'true');
|
||||||
|
|
||||||
|
await resizeElementByHandle(page, [-50, 0], 'bottom-right');
|
||||||
|
await expect(content).toBeHidden();
|
||||||
|
await expect(foldButton).toHaveAttribute('data-folded', 'true');
|
||||||
|
|
||||||
|
await resizeElementByHandle(page, [0, 50], 'bottom-right');
|
||||||
|
await expect(
|
||||||
|
content,
|
||||||
|
'should unfold the embed synced doc when adjust height to greater'
|
||||||
|
).toBeVisible();
|
||||||
|
await expect(foldButton).toHaveAttribute('data-folded', 'false');
|
||||||
|
await expect(content).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user