mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-24 18:02:47 +08:00
feat(core): allow bs snapshot dragging targets (#9093)
fix AF-1924, AF-1848, AF-1928, AF-1931
dnd between affine & editor
<div class='graphite__hidden'>
<div>🎥 Video uploaded on Graphite:</div>
<a href="https://app.graphite.dev/media/video/T2klNLEk0wxLh4NRDzhk/dff3ceb1-dc82-4222-9b55-13be80b28b2f.mp4">
<img src="https://app.graphite.dev/api/v1/graphite/video/thumbnail/T2klNLEk0wxLh4NRDzhk/dff3ceb1-dc82-4222-9b55-13be80b28b2f.mp4">
</a>
</div>
<video src="https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/T2klNLEk0wxLh4NRDzhk/dff3ceb1-dc82-4222-9b55-13be80b28b2f.mp4">20241210-1217-49.8960381.mp4</video>
This commit is contained in:
@@ -243,3 +243,83 @@ test('drag a page link in editor to favourites', async ({ page }) => {
|
||||
pageId
|
||||
);
|
||||
});
|
||||
|
||||
async function enableNewDND(page: Page) {
|
||||
await page.evaluate(() => {
|
||||
// @ts-expect-error
|
||||
window.currentEditor.doc.awarenessStore.setFlag('enable_new_dnd', true);
|
||||
});
|
||||
}
|
||||
|
||||
test('drag a page card block to another page', async ({ page }) => {
|
||||
await enableNewDND(page);
|
||||
await clickNewPageButton(page);
|
||||
await page.waitForTimeout(500);
|
||||
await page.keyboard.press('Enter');
|
||||
await createLinkedPage(page, 'hi from another page');
|
||||
|
||||
const pageReference = page.locator('a').filter({
|
||||
has: page.locator(
|
||||
'.affine-reference-title:has-text("hi from another page")'
|
||||
),
|
||||
});
|
||||
|
||||
const pageLink = await pageReference.evaluate(
|
||||
el => (el as HTMLAnchorElement).href
|
||||
);
|
||||
|
||||
expect(pageLink).toBeTruthy();
|
||||
|
||||
if (!pageLink) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pageId = getDocIdFromUrl(pageLink);
|
||||
|
||||
await pageReference.hover();
|
||||
|
||||
const inlineToolbar = page.locator('reference-popup');
|
||||
|
||||
// convert page reference to card block
|
||||
await inlineToolbar.getByRole('button', { name: 'Switch view' }).click();
|
||||
await inlineToolbar.getByRole('button', { name: 'Card view' }).click();
|
||||
|
||||
// hover the card block to show the drag handle
|
||||
const box = await page.locator('affine-embed-linked-doc-block').boundingBox();
|
||||
|
||||
expect(box).toBeTruthy();
|
||||
|
||||
if (!box) {
|
||||
return;
|
||||
}
|
||||
|
||||
await page.mouse.move(box.x - 5, box.y + box.height / 2);
|
||||
|
||||
await dragToFavourites(
|
||||
page,
|
||||
page.locator('.affine-drag-handle-container'),
|
||||
pageId
|
||||
);
|
||||
});
|
||||
|
||||
test('drag a favourite page into blocksuite', async ({ page }) => {
|
||||
await enableNewDND(page);
|
||||
await clickNewPageButton(page, 'hi from page');
|
||||
await page.getByTestId('pin-button').click();
|
||||
const pageId = getCurrentDocIdFromUrl(page);
|
||||
const item = page
|
||||
.getByTestId(`explorer-favorites`)
|
||||
.locator(`[data-testid="explorer-doc-${pageId}"]`);
|
||||
await expect(item).toBeVisible();
|
||||
|
||||
// drag item into blocksuite editor
|
||||
await dragTo(
|
||||
page,
|
||||
item,
|
||||
page.locator('.affine-paragraph-block-container').first()
|
||||
);
|
||||
|
||||
await expect(page.locator('affine-embed-linked-doc-block')).toContainText(
|
||||
'hi from page'
|
||||
);
|
||||
});
|
||||
|
||||
@@ -95,52 +95,88 @@ export const getPageByTitle = (page: Page, title: string) => {
|
||||
return page.getByTestId('page-list-item').getByText(title);
|
||||
};
|
||||
|
||||
export type DragLocation =
|
||||
| 'top-left'
|
||||
| 'top'
|
||||
| 'bottom'
|
||||
| 'center'
|
||||
| 'left'
|
||||
| 'right';
|
||||
|
||||
export const toPosition = (
|
||||
rect: {
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
},
|
||||
location: DragLocation
|
||||
) => {
|
||||
switch (location) {
|
||||
case 'center':
|
||||
return {
|
||||
x: rect.width / 2,
|
||||
y: rect.height / 2,
|
||||
};
|
||||
case 'top':
|
||||
return { x: rect.width / 2, y: 1 };
|
||||
case 'bottom':
|
||||
return { x: rect.width / 2, y: rect.height - 1 };
|
||||
|
||||
case 'left':
|
||||
return { x: 1, y: rect.height / 2 };
|
||||
|
||||
case 'right':
|
||||
return { x: rect.width - 1, y: rect.height / 2 };
|
||||
|
||||
case 'top-left':
|
||||
default:
|
||||
return { x: 1, y: 1 };
|
||||
}
|
||||
};
|
||||
|
||||
export const dragTo = async (
|
||||
page: Page,
|
||||
locator: Locator,
|
||||
target: Locator,
|
||||
location:
|
||||
| 'top-left'
|
||||
| 'top'
|
||||
| 'bottom'
|
||||
| 'center'
|
||||
| 'left'
|
||||
| 'right' = 'center'
|
||||
location: DragLocation = 'center'
|
||||
) => {
|
||||
await locator.hover();
|
||||
const locatorElement = await locator.boundingBox();
|
||||
if (!locatorElement) {
|
||||
throw new Error('locator element not found');
|
||||
}
|
||||
const locatorCenter = toPosition(locatorElement, 'center');
|
||||
await page.mouse.move(
|
||||
locatorElement.x + locatorCenter.x,
|
||||
locatorElement.y + locatorCenter.y
|
||||
);
|
||||
await page.mouse.down();
|
||||
await page.mouse.move(1, 1);
|
||||
await page.waitForTimeout(100);
|
||||
await page.mouse.move(
|
||||
locatorElement.x + locatorCenter.x + 1,
|
||||
locatorElement.y + locatorCenter.y + 1
|
||||
);
|
||||
|
||||
await page.mouse.move(1, 1, {
|
||||
steps: 10,
|
||||
});
|
||||
|
||||
await target.hover();
|
||||
|
||||
const targetElement = await target.boundingBox();
|
||||
if (!targetElement) {
|
||||
throw new Error('target element not found');
|
||||
}
|
||||
const position = (() => {
|
||||
switch (location) {
|
||||
case 'center':
|
||||
return {
|
||||
x: targetElement.width / 2,
|
||||
y: targetElement.height / 2,
|
||||
};
|
||||
case 'top':
|
||||
return { x: targetElement.width / 2, y: 1 };
|
||||
case 'bottom':
|
||||
return { x: targetElement.width / 2, y: targetElement.height - 1 };
|
||||
|
||||
case 'left':
|
||||
return { x: 1, y: targetElement.height / 2 };
|
||||
|
||||
case 'right':
|
||||
return { x: targetElement.width - 1, y: targetElement.height / 2 };
|
||||
|
||||
case 'top-left':
|
||||
default:
|
||||
return { x: 1, y: 1 };
|
||||
const targetPosition = toPosition(targetElement, location);
|
||||
await page.mouse.move(
|
||||
targetElement.x + targetPosition.x,
|
||||
targetElement.y + targetPosition.y,
|
||||
{
|
||||
steps: 10,
|
||||
}
|
||||
})();
|
||||
await target.hover({
|
||||
position: position,
|
||||
});
|
||||
);
|
||||
await page.waitForTimeout(100);
|
||||
await page.mouse.up();
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user