mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 04:18:54 +00:00
feat(core): add jump to block for cmdk (#4802)
This commit is contained in:
@@ -25,8 +25,10 @@ import {
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
import { pageSettingFamily } from '../atoms';
|
||||
import { fontStyleOptions } from '../atoms/settings';
|
||||
@@ -38,6 +40,10 @@ import * as styles from './page-detail-editor.css';
|
||||
import { editorContainer, pluginContainer } from './page-detail-editor.css';
|
||||
import { TrashButtonGroup } from './pure/trash-button-group';
|
||||
|
||||
function useRouterHash() {
|
||||
return useLocation().hash.substring(1);
|
||||
}
|
||||
|
||||
export type OnLoadEditor = (page: Page, editor: EditorContainer) => () => void;
|
||||
|
||||
export interface PageDetailEditorProps {
|
||||
@@ -65,8 +71,10 @@ const EditorWrapper = memo(function EditorWrapper({
|
||||
const meta = useBlockSuitePageMeta(workspace).find(
|
||||
meta => meta.id === pageId
|
||||
);
|
||||
|
||||
const { switchToEdgelessMode, switchToPageMode } =
|
||||
useBlockSuiteMetaHelper(workspace);
|
||||
|
||||
const pageSettingAtom = pageSettingFamily(pageId);
|
||||
const pageSetting = useAtomValue(pageSettingAtom);
|
||||
const currentMode = pageSetting?.mode ?? 'page';
|
||||
@@ -83,6 +91,29 @@ const EditorWrapper = memo(function EditorWrapper({
|
||||
return fontStyle.value;
|
||||
}, [appSettings.fontStyle]);
|
||||
|
||||
const [loading, setLoading] = useState(true);
|
||||
const blockId = useRouterHash();
|
||||
const blockElement = useMemo(() => {
|
||||
if (!blockId || loading) {
|
||||
return null;
|
||||
}
|
||||
return document.querySelector(`[data-block-id="${blockId}"]`);
|
||||
}, [blockId, loading]);
|
||||
|
||||
useEffect(() => {
|
||||
if (blockElement) {
|
||||
setTimeout(
|
||||
() =>
|
||||
blockElement.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'center',
|
||||
inline: 'center',
|
||||
}),
|
||||
0
|
||||
);
|
||||
}
|
||||
}, [blockElement]);
|
||||
|
||||
const setEditorMode = useCallback(
|
||||
(mode: 'page' | 'edgeless') => {
|
||||
if (mode === 'edgeless') {
|
||||
@@ -153,6 +184,7 @@ const EditorWrapper = memo(function EditorWrapper({
|
||||
window.setTimeout(() => {
|
||||
disposes.forEach(dispose => dispose());
|
||||
});
|
||||
setLoading(false);
|
||||
};
|
||||
},
|
||||
[onLoad]
|
||||
|
||||
@@ -39,6 +39,11 @@ import { WorkspaceSubPath } from '../../../shared';
|
||||
import { usePageHelper } from '../../blocksuite/block-suite-page-list/utils';
|
||||
import type { CMDKCommand, CommandContext } from './types';
|
||||
|
||||
interface SearchResultsValue {
|
||||
space: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
export const cmdkQueryAtom = atom('');
|
||||
export const cmdkValueAtom = atom('');
|
||||
|
||||
@@ -153,7 +158,8 @@ export const pageToCommand = (
|
||||
label?: {
|
||||
title: string;
|
||||
subTitle?: string;
|
||||
}
|
||||
},
|
||||
blockId?: string
|
||||
): CMDKCommand => {
|
||||
const pageMode = store.get(pageSettingsAtom)?.[page.id]?.mode;
|
||||
const currentWorkspaceId = store.get(currentWorkspaceIdAtom);
|
||||
@@ -177,7 +183,14 @@ export const pageToCommand = (
|
||||
console.error('current workspace not found');
|
||||
return;
|
||||
}
|
||||
navigationHelper.jumpToPage(currentWorkspaceId, page.id);
|
||||
if (blockId) {
|
||||
return navigationHelper.jumpToPageBlock(
|
||||
currentWorkspaceId,
|
||||
page.id,
|
||||
blockId
|
||||
);
|
||||
}
|
||||
return navigationHelper.jumpToPage(currentWorkspaceId, page.id);
|
||||
},
|
||||
icon: pageMode === 'edgeless' ? <EdgelessIcon /> : <PageIcon />,
|
||||
timestamp: page.updatedDate,
|
||||
@@ -205,17 +218,23 @@ export const usePageCommands = () => {
|
||||
});
|
||||
} else {
|
||||
// queried pages that has matched contents
|
||||
const searchResults = Array.from(
|
||||
workspace.blockSuiteWorkspace.search({ query }).values()
|
||||
) as unknown as { space: string; content: string }[];
|
||||
// TODO: we shall have a debounce for global search here
|
||||
const searchResults = workspace.blockSuiteWorkspace.search({
|
||||
query,
|
||||
}) as unknown as Map<string, SearchResultsValue>;
|
||||
const resultValues = Array.from(searchResults.values());
|
||||
|
||||
const pageIds = searchResults.map(result => {
|
||||
const pageIds = resultValues.map(result => {
|
||||
if (result.space.startsWith('space:')) {
|
||||
return result.space.slice(6);
|
||||
} else {
|
||||
return result.space;
|
||||
}
|
||||
});
|
||||
const reverseMapping: Map<string, string> = new Map();
|
||||
searchResults.forEach((value, key) => {
|
||||
reverseMapping.set(value.space, key);
|
||||
});
|
||||
|
||||
results = pages.map(page => {
|
||||
const pageMode = store.get(pageSettingsAtom)?.[page.id]?.mode;
|
||||
@@ -225,17 +244,20 @@ export const usePageCommands = () => {
|
||||
const label = {
|
||||
title: page.title || t['Untitled'](), // Used to ensure that a title exists
|
||||
subTitle:
|
||||
searchResults.find(result => result.space === page.id)?.content ||
|
||||
resultValues.find(result => result.space === page.id)?.content ||
|
||||
'',
|
||||
};
|
||||
|
||||
const blockId = reverseMapping.get(page.id);
|
||||
|
||||
const command = pageToCommand(
|
||||
category,
|
||||
page,
|
||||
store,
|
||||
navigationHelper,
|
||||
t,
|
||||
label
|
||||
label,
|
||||
blockId
|
||||
);
|
||||
|
||||
if (pageIds.includes(page.id)) {
|
||||
|
||||
@@ -29,6 +29,19 @@ export function useNavigateHelper() {
|
||||
},
|
||||
[navigate]
|
||||
);
|
||||
const jumpToPageBlock = useCallback(
|
||||
(
|
||||
workspaceId: string,
|
||||
pageId: string,
|
||||
blockId: string,
|
||||
logic: RouteLogic = RouteLogic.PUSH
|
||||
) => {
|
||||
return navigate(`/workspace/${workspaceId}/${pageId}#${blockId}`, {
|
||||
replace: logic === RouteLogic.REPLACE,
|
||||
});
|
||||
},
|
||||
[navigate]
|
||||
);
|
||||
const jumpToCollection = useCallback(
|
||||
(
|
||||
workspaceId: string,
|
||||
@@ -122,6 +135,7 @@ export function useNavigateHelper() {
|
||||
return useMemo(
|
||||
() => ({
|
||||
jumpToPage,
|
||||
jumpToPageBlock,
|
||||
jumpToPublicWorkspacePage,
|
||||
jumpToSubPath,
|
||||
jumpToIndex,
|
||||
@@ -132,14 +146,15 @@ export function useNavigateHelper() {
|
||||
jumpToCollection,
|
||||
}),
|
||||
[
|
||||
jumpTo404,
|
||||
jumpToExpired,
|
||||
jumpToIndex,
|
||||
jumpToPage,
|
||||
jumpToPageBlock,
|
||||
jumpToPublicWorkspacePage,
|
||||
jumpToSignIn,
|
||||
jumpToSubPath,
|
||||
jumpToIndex,
|
||||
jumpTo404,
|
||||
openPage,
|
||||
jumpToExpired,
|
||||
jumpToSignIn,
|
||||
jumpToCollection,
|
||||
]
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user