From 8427293d368fd96865c1fb2f0e840d1b69eb5186 Mon Sep 17 00:00:00 2001 From: fundon Date: Tue, 1 Apr 2025 14:46:34 +0000 Subject: [PATCH] fix(core): fix target block cannot be reached when clicking affine-link multiple times (#10473) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes: [BS-2702](https://linear.app/affine-design/issue/BS-2702/超链接无法滚动到指定block) --- .../components/hooks/use-navigate-helper.ts | 8 ++- .../workspace/detail-page/detail-page.tsx | 2 + tests/affine-local/e2e/links.spec.ts | 59 +++++++++++++++++++ .../e2e/local-first-openpage-newtab.spec.ts | 6 +- 4 files changed, 73 insertions(+), 2 deletions(-) diff --git a/packages/frontend/core/src/components/hooks/use-navigate-helper.ts b/packages/frontend/core/src/components/hooks/use-navigate-helper.ts index dd0e2990b..25e9981b2 100644 --- a/packages/frontend/core/src/components/hooks/use-navigate-helper.ts +++ b/packages/frontend/core/src/components/hooks/use-navigate-helper.ts @@ -2,6 +2,7 @@ import type { SettingTab } from '@affine/core/modules/dialogs/constant'; import { toURLSearchParams } from '@affine/core/modules/navigation'; import { getOpenUrlInDesktopAppLink } from '@affine/core/modules/open-in-app'; import type { DocMode } from '@blocksuite/affine/model'; +import { nanoid } from 'nanoid'; import { createContext, useCallback, useContext, useMemo } from 'react'; import type { NavigateFunction, NavigateOptions } from 'react-router-dom'; @@ -48,7 +49,12 @@ export function useNavigateHelper() { elementIds?: string[], logic: RouteLogic = RouteLogic.PUSH ) => { - const search = toURLSearchParams({ mode, blockIds, elementIds }); + const search = toURLSearchParams({ + mode, + blockIds, + elementIds, + refreshKey: nanoid(), + }); const query = search?.size ? `?${search.toString()}` : ''; return navigate(`/workspace/${workspaceId}/${pageId}${query}`, { replace: logic === RouteLogic.REPLACE, diff --git a/packages/frontend/core/src/desktop/pages/workspace/detail-page/detail-page.tsx b/packages/frontend/core/src/desktop/pages/workspace/detail-page/detail-page.tsx index 79248d11b..005df1ed7 100644 --- a/packages/frontend/core/src/desktop/pages/workspace/detail-page/detail-page.tsx +++ b/packages/frontend/core/src/desktop/pages/workspace/detail-page/detail-page.tsx @@ -34,6 +34,7 @@ import { useServices, } from '@toeverything/infra'; import clsx from 'clsx'; +import { nanoid } from 'nanoid'; import { memo, useCallback, useEffect, useRef, useState } from 'react'; import { useParams } from 'react-router-dom'; import type { Subscription } from 'rxjs'; @@ -207,6 +208,7 @@ const DetailPageImpl = memo(function DetailPageImpl() { mode: params?.mode, blockIds: params?.blockIds, elementIds: params?.elementIds, + refreshKey: nanoid(), }, { at: at, diff --git a/tests/affine-local/e2e/links.spec.ts b/tests/affine-local/e2e/links.spec.ts index 3b982159a..0eeb58fc6 100644 --- a/tests/affine-local/e2e/links.spec.ts +++ b/tests/affine-local/e2e/links.spec.ts @@ -3,6 +3,7 @@ import { test } from '@affine-test/kit/playwright'; import { clickEdgelessModeButton } from '@affine-test/kit/utils/editor'; import { pasteByKeyboard, + selectAllByKeyboard, writeTextToClipboard, } from '@affine-test/kit/utils/keyboard'; 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'); }); + +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); +}); diff --git a/tests/affine-local/e2e/local-first-openpage-newtab.spec.ts b/tests/affine-local/e2e/local-first-openpage-newtab.spec.ts index e322c7d5f..48156a92c 100644 --- a/tests/affine-local/e2e/local-first-openpage-newtab.spec.ts +++ b/tests/affine-local/e2e/local-first-openpage-newtab.spec.ts @@ -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); });