mirror of
https://github.com/toeverything/AFFiNE.git
synced 2025-01-02 16:57:07 +03:00
fix(core): polling to search in cmdk (#5274)
This is a temporary solution until https://github.com/toeverything/blocksuite/issues/5668 be solved.
This commit is contained in:
parent
9aa33d0228
commit
b782b3fb1b
@ -25,7 +25,7 @@ import {
|
||||
} from '@toeverything/infra/command';
|
||||
import { atom, useAtomValue } from 'jotai';
|
||||
import { groupBy } from 'lodash-es';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import {
|
||||
openQuickSearchModalAtom,
|
||||
@ -173,13 +173,21 @@ export const pageToCommand = (
|
||||
title: title,
|
||||
};
|
||||
|
||||
// hack: when comparing, the part between >>> and <<< will be ignored
|
||||
// adding this patch so that CMDK will not complain about duplicated commands
|
||||
const id =
|
||||
title +
|
||||
(label?.subTitle || '') +
|
||||
valueWrapperStart +
|
||||
page.id +
|
||||
'.' +
|
||||
category +
|
||||
valueWrapperEnd;
|
||||
|
||||
return {
|
||||
id: page.id,
|
||||
id,
|
||||
label: commandLabel,
|
||||
// hack: when comparing, the part between >>> and <<< will be ignored
|
||||
// adding this patch so that CMDK will not complain about duplicated commands
|
||||
value:
|
||||
title + valueWrapperStart + page.id + '.' + category + valueWrapperEnd,
|
||||
value: id,
|
||||
originalValue: title,
|
||||
category: category,
|
||||
run: () => {
|
||||
@ -216,7 +224,25 @@ export const usePageCommands = () => {
|
||||
const navigationHelper = useNavigateHelper();
|
||||
const t = useAFFiNEI18N();
|
||||
|
||||
const [searchTime, setSearchTime] = useState<number>(0);
|
||||
|
||||
// HACK: blocksuite indexer is async,
|
||||
// so we need to re-search after it has been updated
|
||||
useEffect(() => {
|
||||
let timer: NodeJS.Timeout | null = null;
|
||||
const dosearch = () => {
|
||||
setSearchTime(Date.now());
|
||||
timer = setTimeout(dosearch, 500);
|
||||
};
|
||||
timer = setTimeout(dosearch, 500);
|
||||
return () => {
|
||||
if (timer) clearTimeout(timer);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return useMemo(() => {
|
||||
searchTime; // hack to make the searchTime as a dependency
|
||||
|
||||
let results: CMDKCommand[] = [];
|
||||
if (query.trim() === '') {
|
||||
results = recentPages.map(page => {
|
||||
@ -322,6 +348,7 @@ export const usePageCommands = () => {
|
||||
store,
|
||||
t,
|
||||
workspace.blockSuiteWorkspace,
|
||||
searchTime,
|
||||
]);
|
||||
};
|
||||
|
||||
|
@ -7,7 +7,13 @@ import { useAsyncCallback } from '@toeverything/hooks/affine-async-hooks';
|
||||
import type { CommandCategory } from '@toeverything/infra/command';
|
||||
import clsx from 'clsx';
|
||||
import { useAtom, useAtomValue } from 'jotai';
|
||||
import { Suspense, useLayoutEffect, useMemo, useState } from 'react';
|
||||
import {
|
||||
Suspense,
|
||||
useCallback,
|
||||
useLayoutEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react';
|
||||
|
||||
import {
|
||||
cmdkQueryAtom,
|
||||
@ -189,6 +195,12 @@ export const CMDKContainer = ({
|
||||
const isInEditor = pageMeta !== undefined;
|
||||
const [opening, setOpening] = useState(open);
|
||||
|
||||
const handleFocus = useCallback((ref: HTMLInputElement | null) => {
|
||||
if (ref) {
|
||||
window.setTimeout(() => ref.focus(), 0);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// fix list height animation on openning
|
||||
useLayoutEffect(() => {
|
||||
if (open) {
|
||||
@ -235,7 +247,7 @@ export const CMDKContainer = ({
|
||||
) : null}
|
||||
<Command.Input
|
||||
placeholder={t['com.affine.cmdk.placeholder']()}
|
||||
autoFocus
|
||||
ref={handleFocus}
|
||||
{...rest}
|
||||
value={query}
|
||||
onValueChange={onQueryChange}
|
||||
|
@ -16,6 +16,12 @@ const openQuickSearchByShortcut = async (page: Page, checkVisible = true) => {
|
||||
}
|
||||
};
|
||||
|
||||
const insertInputText = async (page: Page, text: string) => {
|
||||
await page.locator('[cmdk-input]').fill(text);
|
||||
const actual = await page.locator('[cmdk-input]').inputValue();
|
||||
expect(actual).toBe(text);
|
||||
};
|
||||
|
||||
const keyboardDownAndSelect = async (page: Page, label: string) => {
|
||||
await page.keyboard.press('ArrowDown');
|
||||
if (
|
||||
@ -77,14 +83,16 @@ async function waitForScrollToFinish(page: Page) {
|
||||
}
|
||||
|
||||
async function assertResultList(page: Page, texts: string[]) {
|
||||
const actual = await page
|
||||
.locator('[cmdk-item] [data-testid=cmdk-label]')
|
||||
.allInnerTexts();
|
||||
const actualSplit = actual[0].split('\n');
|
||||
expect(actualSplit[0]).toEqual(texts[0]);
|
||||
if (actualSplit[1]) {
|
||||
expect(actualSplit[1]).toEqual(texts[1]);
|
||||
}
|
||||
await expect(async () => {
|
||||
const actual = await page
|
||||
.locator('[cmdk-item] [data-testid=cmdk-label]')
|
||||
.allInnerTexts();
|
||||
const actualSplit = actual[0].split('\n');
|
||||
expect(actualSplit[0]).toEqual(texts[0]);
|
||||
if (actualSplit[1]) {
|
||||
expect(actualSplit[1]).toEqual(texts[1]);
|
||||
}
|
||||
}).toPass();
|
||||
}
|
||||
|
||||
async function titleIsFocused(page: Page) {
|
||||
@ -137,7 +145,7 @@ test('Create a new page with keyword', async ({ page }) => {
|
||||
await waitForEditorLoad(page);
|
||||
await clickNewPageButton(page);
|
||||
await openQuickSearchByShortcut(page);
|
||||
await page.keyboard.insertText('"test123456"');
|
||||
await insertInputText(page, '"test123456"');
|
||||
const addNewPage = page.locator(
|
||||
'[cmdk-item] >> text=New ""test123456"" Page'
|
||||
);
|
||||
@ -151,9 +159,7 @@ test('Enter a keyword to search for', async ({ page }) => {
|
||||
await waitForEditorLoad(page);
|
||||
await clickNewPageButton(page);
|
||||
await openQuickSearchByShortcut(page);
|
||||
await page.keyboard.insertText('test123456');
|
||||
const actual = await page.locator('[cmdk-input]').inputValue();
|
||||
expect(actual).toBe('test123456');
|
||||
await insertInputText(page, 'test123456');
|
||||
});
|
||||
|
||||
test('Create a new page and search this page', async ({ page }) => {
|
||||
@ -162,7 +168,7 @@ test('Create a new page and search this page', async ({ page }) => {
|
||||
await clickNewPageButton(page);
|
||||
await openQuickSearchByShortcut(page);
|
||||
// input title and create new page
|
||||
await page.keyboard.insertText('test123456');
|
||||
await insertInputText(page, 'test123456');
|
||||
await page.waitForTimeout(300);
|
||||
const addNewPage = page.locator('[cmdk-item] >> text=New "test123456" Page');
|
||||
await addNewPage.click();
|
||||
@ -170,7 +176,7 @@ test('Create a new page and search this page', async ({ page }) => {
|
||||
await page.waitForTimeout(300);
|
||||
await assertTitle(page, 'test123456');
|
||||
await openQuickSearchByShortcut(page);
|
||||
await page.keyboard.insertText('test123456');
|
||||
await insertInputText(page, 'test123456');
|
||||
await page.waitForTimeout(300);
|
||||
await assertResultList(page, ['test123456', 'test123456']);
|
||||
await page.keyboard.press('Enter');
|
||||
@ -180,7 +186,7 @@ test('Create a new page and search this page', async ({ page }) => {
|
||||
await page.reload();
|
||||
await waitForEditorLoad(page);
|
||||
await openQuickSearchByShortcut(page);
|
||||
await page.keyboard.insertText('test123456');
|
||||
await insertInputText(page, 'test123456');
|
||||
await page.waitForTimeout(300);
|
||||
await assertResultList(page, ['test123456', 'test123456']);
|
||||
await page.keyboard.press('Enter');
|
||||
@ -375,7 +381,7 @@ test('show not found item', async ({ page }) => {
|
||||
await clickNewPageButton(page);
|
||||
await openQuickSearchByShortcut(page);
|
||||
// input title and create new page
|
||||
await page.keyboard.insertText('test123456');
|
||||
await insertInputText(page, 'test123456');
|
||||
const notFoundItem = page.getByTestId('cmdk-search-not-found');
|
||||
await expect(notFoundItem).toBeVisible();
|
||||
await expect(notFoundItem).toHaveText('Search for "test123456"');
|
||||
@ -395,15 +401,17 @@ test('can use cmdk to search page content and scroll to it, then the block will
|
||||
await page.keyboard.press('Enter', { delay: 10 });
|
||||
}
|
||||
await page.keyboard.insertText('123456');
|
||||
const textBlock = page.getByText('123456');
|
||||
await expect(textBlock).toBeVisible();
|
||||
await clickSideBarAllPageButton(page);
|
||||
await openQuickSearchByShortcut(page);
|
||||
await page.keyboard.insertText('123456');
|
||||
await insertInputText(page, '123456');
|
||||
await page.waitForTimeout(300);
|
||||
await assertResultList(page, [
|
||||
'this is a new page to search for content',
|
||||
'123456',
|
||||
]);
|
||||
await page.keyboard.press('Enter');
|
||||
await page.locator('[cmdk-item] [data-testid=cmdk-label]').first().click();
|
||||
await waitForScrollToFinish(page);
|
||||
const isVisitable = await checkElementIsInView(page, '123456');
|
||||
expect(isVisitable).toBe(true);
|
||||
@ -424,7 +432,7 @@ test('Create a new page with special characters in the title and search for this
|
||||
await getBlockSuiteEditorTitle(page).fill(specialTitle);
|
||||
await openQuickSearchByShortcut(page);
|
||||
|
||||
await page.keyboard.insertText(specialTitle);
|
||||
await insertInputText(page, specialTitle);
|
||||
await page.waitForTimeout(300);
|
||||
|
||||
await assertResultList(page, [specialTitle, specialTitle]);
|
||||
|
Loading…
Reference in New Issue
Block a user