fix(core): fix target block cannot be reached when clicking affine-link multiple times (#10473)
Closes: [BS-2702](https://linear.app/affine-design/issue/BS-2702/超链接无法滚动到指定block)
This commit is contained in:
@@ -2,6 +2,7 @@ import type { SettingTab } from '@affine/core/modules/dialogs/constant';
|
|||||||
import { toURLSearchParams } from '@affine/core/modules/navigation';
|
import { toURLSearchParams } from '@affine/core/modules/navigation';
|
||||||
import { getOpenUrlInDesktopAppLink } from '@affine/core/modules/open-in-app';
|
import { getOpenUrlInDesktopAppLink } from '@affine/core/modules/open-in-app';
|
||||||
import type { DocMode } from '@blocksuite/affine/model';
|
import type { DocMode } from '@blocksuite/affine/model';
|
||||||
|
import { nanoid } from 'nanoid';
|
||||||
import { createContext, useCallback, useContext, useMemo } from 'react';
|
import { createContext, useCallback, useContext, useMemo } from 'react';
|
||||||
import type { NavigateFunction, NavigateOptions } from 'react-router-dom';
|
import type { NavigateFunction, NavigateOptions } from 'react-router-dom';
|
||||||
|
|
||||||
@@ -48,7 +49,12 @@ export function useNavigateHelper() {
|
|||||||
elementIds?: string[],
|
elementIds?: string[],
|
||||||
logic: RouteLogic = RouteLogic.PUSH
|
logic: RouteLogic = RouteLogic.PUSH
|
||||||
) => {
|
) => {
|
||||||
const search = toURLSearchParams({ mode, blockIds, elementIds });
|
const search = toURLSearchParams({
|
||||||
|
mode,
|
||||||
|
blockIds,
|
||||||
|
elementIds,
|
||||||
|
refreshKey: nanoid(),
|
||||||
|
});
|
||||||
const query = search?.size ? `?${search.toString()}` : '';
|
const query = search?.size ? `?${search.toString()}` : '';
|
||||||
return navigate(`/workspace/${workspaceId}/${pageId}${query}`, {
|
return navigate(`/workspace/${workspaceId}/${pageId}${query}`, {
|
||||||
replace: logic === RouteLogic.REPLACE,
|
replace: logic === RouteLogic.REPLACE,
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import {
|
|||||||
useServices,
|
useServices,
|
||||||
} from '@toeverything/infra';
|
} from '@toeverything/infra';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
import { nanoid } from 'nanoid';
|
||||||
import { memo, useCallback, useEffect, useRef, useState } from 'react';
|
import { memo, useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import type { Subscription } from 'rxjs';
|
import type { Subscription } from 'rxjs';
|
||||||
@@ -207,6 +208,7 @@ const DetailPageImpl = memo(function DetailPageImpl() {
|
|||||||
mode: params?.mode,
|
mode: params?.mode,
|
||||||
blockIds: params?.blockIds,
|
blockIds: params?.blockIds,
|
||||||
elementIds: params?.elementIds,
|
elementIds: params?.elementIds,
|
||||||
|
refreshKey: nanoid(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
at: at,
|
at: at,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { test } from '@affine-test/kit/playwright';
|
|||||||
import { clickEdgelessModeButton } from '@affine-test/kit/utils/editor';
|
import { clickEdgelessModeButton } from '@affine-test/kit/utils/editor';
|
||||||
import {
|
import {
|
||||||
pasteByKeyboard,
|
pasteByKeyboard,
|
||||||
|
selectAllByKeyboard,
|
||||||
writeTextToClipboard,
|
writeTextToClipboard,
|
||||||
} from '@affine-test/kit/utils/keyboard';
|
} from '@affine-test/kit/utils/keyboard';
|
||||||
import { coreUrl, openHomePage } from '@affine-test/kit/utils/load-page';
|
import { coreUrl, openHomePage } from '@affine-test/kit/utils/load-page';
|
||||||
@@ -1164,3 +1165,61 @@ test('should not show view toggle button when protocol of link is not http(s)',
|
|||||||
|
|
||||||
await expect(toolbar.locator('affine-link-preview')).toHaveText('affine.pro');
|
await expect(toolbar.locator('affine-link-preview')).toHaveText('affine.pro');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should reach target block when clicking affine-link multiple times', async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
await page.keyboard.press('Enter');
|
||||||
|
await page.keyboard.type('a');
|
||||||
|
|
||||||
|
await page.keyboard.press('Enter');
|
||||||
|
await page.keyboard.type('b');
|
||||||
|
|
||||||
|
await page.keyboard.press('Enter');
|
||||||
|
await page.keyboard.type('c');
|
||||||
|
|
||||||
|
await selectAllByKeyboard(page);
|
||||||
|
|
||||||
|
const { toolbar } = toolbarButtons(page);
|
||||||
|
|
||||||
|
await toolbar.getByLabel('More menu').click();
|
||||||
|
await toolbar.getByLabel('Copy link to block').click();
|
||||||
|
|
||||||
|
const paragraph = page.locator('affine-paragraph').nth(0);
|
||||||
|
await paragraph.click();
|
||||||
|
|
||||||
|
await selectAllByKeyboard(page);
|
||||||
|
|
||||||
|
await toolbar.getByLabel(/^Link$/).click();
|
||||||
|
|
||||||
|
await page.waitForSelector('.affine-link-popover');
|
||||||
|
|
||||||
|
await pasteByKeyboard(page);
|
||||||
|
|
||||||
|
await page.locator('.affine-confirm-button').click();
|
||||||
|
|
||||||
|
const scrollAnchoringWidget = page.locator('affine-scroll-anchoring-widget');
|
||||||
|
const highlight = scrollAnchoringWidget.locator('.highlight');
|
||||||
|
|
||||||
|
const inlineLink = page.locator('affine-link');
|
||||||
|
|
||||||
|
await inlineLink.click();
|
||||||
|
await expect(highlight).toBeVisible();
|
||||||
|
const url0 = new URL(page.url());
|
||||||
|
const refreshKey0 = url0.searchParams.get('refreshKey');
|
||||||
|
expect(refreshKey0).not.toBeNull();
|
||||||
|
|
||||||
|
await paragraph.click();
|
||||||
|
await expect(highlight).toBeHidden();
|
||||||
|
|
||||||
|
await inlineLink.click();
|
||||||
|
await expect(highlight).toBeVisible();
|
||||||
|
const url1 = new URL(page.url());
|
||||||
|
const refreshKey1 = url1.searchParams.get('refreshKey');
|
||||||
|
expect(refreshKey1).not.toBeNull();
|
||||||
|
|
||||||
|
await paragraph.click();
|
||||||
|
await expect(highlight).toBeHidden();
|
||||||
|
|
||||||
|
expect(refreshKey0).not.toEqual(refreshKey1);
|
||||||
|
});
|
||||||
|
|||||||
@@ -142,5 +142,9 @@ test('ctrl click embedded doc link and open in new tab', async ({ page }) => {
|
|||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await expect(newTabPage).toHaveURL(newPageUrl, { timeout: 15000 });
|
const newTabPageUrl = new URL(newTabPage.url());
|
||||||
|
// ignores `search params`
|
||||||
|
newTabPageUrl.search = '';
|
||||||
|
|
||||||
|
expect(newTabPageUrl.toString()).toBe(newPageUrl);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user