mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-09-07 01:09:54 +08:00
fix: insert link action in quick search callback (#7165)
This commit is contained in:
@@ -16,9 +16,11 @@ import { CollectionService } from '@affine/core/modules/collection';
|
|||||||
import { WorkspaceSubPath } from '@affine/core/shared';
|
import { WorkspaceSubPath } from '@affine/core/shared';
|
||||||
import { mixpanel } from '@affine/core/utils';
|
import { mixpanel } from '@affine/core/utils';
|
||||||
import type { Collection } from '@affine/env/filter';
|
import type { Collection } from '@affine/env/filter';
|
||||||
|
import { Trans } from '@affine/i18n';
|
||||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
import {
|
import {
|
||||||
EdgelessIcon,
|
EdgelessIcon,
|
||||||
|
LinkIcon,
|
||||||
PageIcon,
|
PageIcon,
|
||||||
TodayIcon,
|
TodayIcon,
|
||||||
ViewLayersIcon,
|
ViewLayersIcon,
|
||||||
@@ -36,6 +38,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
|
|||||||
import { usePageHelper } from '../../../components/blocksuite/block-suite-page-list/utils';
|
import { usePageHelper } from '../../../components/blocksuite/block-suite-page-list/utils';
|
||||||
import { useNavigateHelper } from '../../../hooks/use-navigate-helper';
|
import { useNavigateHelper } from '../../../hooks/use-navigate-helper';
|
||||||
import { filterSortAndGroupCommands } from './filter-commands';
|
import { filterSortAndGroupCommands } from './filter-commands';
|
||||||
|
import * as hlStyles from './highlight.css';
|
||||||
import type { CMDKCommand, CommandContext } from './types';
|
import type { CMDKCommand, CommandContext } from './types';
|
||||||
|
|
||||||
export const cmdkValueAtom = atom('');
|
export const cmdkValueAtom = atom('');
|
||||||
@@ -254,9 +257,17 @@ export const usePageCommands = () => {
|
|||||||
|
|
||||||
results.push({
|
results.push({
|
||||||
id: 'affine:pages:create-page',
|
id: 'affine:pages:create-page',
|
||||||
label: t['com.affine.cmdk.affine.create-new-page-as']({
|
label: (
|
||||||
keyWord: query,
|
<Trans
|
||||||
}),
|
i18nKey="com.affine.cmdk.affine.create-new-page-as"
|
||||||
|
values={{
|
||||||
|
keyWord: query,
|
||||||
|
}}
|
||||||
|
components={{
|
||||||
|
1: <span className={hlStyles.highlightKeyword} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
alwaysShow: true,
|
alwaysShow: true,
|
||||||
category: 'affine:creation',
|
category: 'affine:creation',
|
||||||
run: async () => {
|
run: async () => {
|
||||||
@@ -273,9 +284,17 @@ export const usePageCommands = () => {
|
|||||||
|
|
||||||
results.push({
|
results.push({
|
||||||
id: 'affine:pages:create-edgeless',
|
id: 'affine:pages:create-edgeless',
|
||||||
label: t['com.affine.cmdk.affine.create-new-edgeless-as']({
|
label: (
|
||||||
keyWord: query,
|
<Trans
|
||||||
}),
|
i18nKey="com.affine.cmdk.affine.create-new-edgeless-as"
|
||||||
|
values={{
|
||||||
|
keyWord: query,
|
||||||
|
}}
|
||||||
|
components={{
|
||||||
|
1: <span className={hlStyles.highlightKeyword} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
alwaysShow: true,
|
alwaysShow: true,
|
||||||
category: 'affine:creation',
|
category: 'affine:creation',
|
||||||
run: async () => {
|
run: async () => {
|
||||||
@@ -309,7 +328,6 @@ export const useSearchCallbackCommands = () => {
|
|||||||
const pageHelper = usePageHelper(workspace.docCollection);
|
const pageHelper = usePageHelper(workspace.docCollection);
|
||||||
const pageMetaHelper = useDocMetaHelper(workspace.docCollection);
|
const pageMetaHelper = useDocMetaHelper(workspace.docCollection);
|
||||||
const query = useLiveData(quickSearch.query$);
|
const query = useLiveData(quickSearch.query$);
|
||||||
const t = useAFFiNEI18N();
|
|
||||||
|
|
||||||
const onSelectPage = useCallback(
|
const onSelectPage = useCallback(
|
||||||
(searchResult: SearchCallbackResult) => {
|
(searchResult: SearchCallbackResult) => {
|
||||||
@@ -332,35 +350,52 @@ export const useSearchCallbackCommands = () => {
|
|||||||
results.every(command => command.originalValue !== query) &&
|
results.every(command => command.originalValue !== query) &&
|
||||||
query.trim()
|
query.trim()
|
||||||
) {
|
) {
|
||||||
results.push({
|
if (query.startsWith('http://') || query.startsWith('https://')) {
|
||||||
id: 'affine:pages:create-page',
|
results.push({
|
||||||
label: t['com.affine.cmdk.affine.create-new-doc-and-insert']({
|
id: 'affine:pages:create-page',
|
||||||
keyWord: query,
|
label: <Trans i18nKey="com.affine.cmdk.affine.insert-link" />,
|
||||||
}),
|
alwaysShow: true,
|
||||||
alwaysShow: true,
|
category: 'affine:creation',
|
||||||
category: 'affine:creation',
|
run: async () => {
|
||||||
run: async () => {
|
onSelectPage({
|
||||||
const page = pageHelper.createPage('page', false);
|
query,
|
||||||
page.load();
|
action: 'insert',
|
||||||
pageMetaHelper.setDocTitle(page.id, query);
|
});
|
||||||
mixpanel.track('DocCreated', {
|
},
|
||||||
control: 'cmdk',
|
icon: <LinkIcon />,
|
||||||
type: 'doc',
|
});
|
||||||
});
|
} else {
|
||||||
onSelectPage({ docId: page.id });
|
results.push({
|
||||||
},
|
id: 'affine:pages:create-page',
|
||||||
icon: <PageIcon />,
|
label: (
|
||||||
});
|
<Trans
|
||||||
|
i18nKey="com.affine.cmdk.affine.create-new-doc-and-insert"
|
||||||
|
values={{
|
||||||
|
keyWord: query,
|
||||||
|
}}
|
||||||
|
components={{
|
||||||
|
1: <span className={hlStyles.highlightKeyword} />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
alwaysShow: true,
|
||||||
|
category: 'affine:creation',
|
||||||
|
run: async () => {
|
||||||
|
const page = pageHelper.createPage('page', false);
|
||||||
|
page.load();
|
||||||
|
pageMetaHelper.setDocTitle(page.id, query);
|
||||||
|
mixpanel.track('DocCreated', {
|
||||||
|
control: 'cmdk',
|
||||||
|
type: 'doc',
|
||||||
|
});
|
||||||
|
onSelectPage({ docId: page.id });
|
||||||
|
},
|
||||||
|
icon: <PageIcon />,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}, [
|
}, [searchedDocsCommands, query, pageHelper, pageMetaHelper, onSelectPage]);
|
||||||
searchedDocsCommands,
|
|
||||||
query,
|
|
||||||
t,
|
|
||||||
pageHelper,
|
|
||||||
pageMetaHelper,
|
|
||||||
onSelectPage,
|
|
||||||
]);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const collectionToCommand = (
|
export const collectionToCommand = (
|
||||||
|
|||||||
@@ -74,12 +74,22 @@ export const getCommandScore = (command: CMDKCommand, search: string) => {
|
|||||||
if (search.trim() === '') {
|
if (search.trim() === '') {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const label = command.label;
|
||||||
|
|
||||||
const title =
|
const title =
|
||||||
(typeof command?.label === 'string'
|
label && typeof label === 'object' && 'title' in label
|
||||||
? command.label
|
? label.title
|
||||||
: command?.label.title) || '';
|
: typeof label === 'string'
|
||||||
|
? label
|
||||||
|
: '';
|
||||||
|
|
||||||
const subTitle =
|
const subTitle =
|
||||||
(typeof command?.label === 'string' ? '' : command?.label.subTitle) || '';
|
label && typeof label === 'object' && 'title' in label
|
||||||
|
? label.subTitle ?? ''
|
||||||
|
: typeof label === 'string'
|
||||||
|
? label
|
||||||
|
: '';
|
||||||
|
|
||||||
const catWeight = getCategoryWeight(command.category);
|
const catWeight = getCategoryWeight(command.category);
|
||||||
|
|
||||||
|
|||||||
@@ -10,16 +10,22 @@ export const highlightText = style({
|
|||||||
textOverflow: 'ellipsis',
|
textOverflow: 'ellipsis',
|
||||||
});
|
});
|
||||||
export const highlightKeyword = style({
|
export const highlightKeyword = style({
|
||||||
|
display: 'inline-block',
|
||||||
|
verticalAlign: 'bottom',
|
||||||
color: cssVar('primaryColor'),
|
color: cssVar('primaryColor'),
|
||||||
whiteSpace: 'pre',
|
whiteSpace: 'pre',
|
||||||
overflow: 'visible',
|
overflow: 'hidden',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
|
maxWidth: '360px',
|
||||||
});
|
});
|
||||||
export const labelTitle = style({
|
export const labelTitle = style({
|
||||||
fontSize: cssVar('fontBase'),
|
fontSize: cssVar('fontBase'),
|
||||||
lineHeight: '24px',
|
lineHeight: '24px',
|
||||||
fontWeight: 400,
|
fontWeight: 400,
|
||||||
textAlign: 'justify',
|
textAlign: 'justify',
|
||||||
|
overflow: 'hidden',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
});
|
});
|
||||||
export const labelContent = style({
|
export const labelContent = style({
|
||||||
fontSize: cssVar('fontXs'),
|
fontSize: cssVar('fontXs'),
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { memo } from 'react';
|
import { memo, type ReactNode } from 'react';
|
||||||
|
|
||||||
import * as styles from './highlight.css';
|
import * as styles from './highlight.css';
|
||||||
import { useHighlight } from './use-highlight';
|
import { useHighlight } from './use-highlight';
|
||||||
@@ -14,7 +14,7 @@ type HighlightProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type HighlightLabelProps = {
|
type HighlightLabelProps = {
|
||||||
label: SearchResultLabel;
|
label: SearchResultLabel | ReactNode;
|
||||||
highlight: string;
|
highlight: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -44,16 +44,20 @@ export const HighlightLabel = memo(function HighlightLabel({
|
|||||||
label,
|
label,
|
||||||
highlight,
|
highlight,
|
||||||
}: HighlightLabelProps) {
|
}: HighlightLabelProps) {
|
||||||
return (
|
if (label && typeof label === 'object' && 'title' in label) {
|
||||||
<div>
|
return (
|
||||||
<div className={styles.labelTitle}>
|
<div>
|
||||||
<Highlight text={label.title} highlight={highlight} />
|
<div className={styles.labelTitle}>
|
||||||
</div>
|
<Highlight text={label.title} highlight={highlight} />
|
||||||
{label.subTitle ? (
|
|
||||||
<div className={styles.labelContent}>
|
|
||||||
<Highlight text={label.subTitle} highlight={highlight} />
|
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
{label.subTitle ? (
|
||||||
</div>
|
<div className={styles.labelContent}>
|
||||||
);
|
<Highlight text={label.subTitle} highlight={highlight} />
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className={styles.labelTitle}>{label}</div>;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -174,6 +174,8 @@ export const CMDKContainer = ({
|
|||||||
const [opening, setOpening] = useState(open);
|
const [opening, setOpening] = useState(open);
|
||||||
const { syncing, progress } = useDocEngineStatus();
|
const { syncing, progress } = useDocEngineStatus();
|
||||||
const showLoading = useDebouncedValue(syncing, 500);
|
const showLoading = useDebouncedValue(syncing, 500);
|
||||||
|
const quickSearch = useService(QuickSearchService).quickSearch;
|
||||||
|
const mode = useLiveData(quickSearch.mode$);
|
||||||
|
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
@@ -235,7 +237,7 @@ export const CMDKContainer = ({
|
|||||||
<Command.List data-opening={opening ? true : undefined}>
|
<Command.List data-opening={opening ? true : undefined}>
|
||||||
{children}
|
{children}
|
||||||
</Command.List>
|
</Command.List>
|
||||||
<NotFoundGroup />
|
{mode === 'commands' ? <NotFoundGroup /> : null}
|
||||||
</Command>
|
</Command>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -25,7 +25,10 @@ export const notFoundTitle = style({
|
|||||||
color: cssVar('textSecondaryColor'),
|
color: cssVar('textSecondaryColor'),
|
||||||
fontWeight: '600',
|
fontWeight: '600',
|
||||||
lineHeight: '20px',
|
lineHeight: '20px',
|
||||||
textAlign: 'justify',
|
whiteSpace: 'nowrap',
|
||||||
|
wordBreak: 'break-word',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
overflow: 'hidden',
|
||||||
padding: '8px',
|
padding: '8px',
|
||||||
});
|
});
|
||||||
export const notFoundText = style({
|
export const notFoundText = style({
|
||||||
|
|||||||
@@ -9,10 +9,8 @@ import * as styles from './not-found.css';
|
|||||||
export const NotFoundGroup = () => {
|
export const NotFoundGroup = () => {
|
||||||
const quickSearch = useService(QuickSearchService).quickSearch;
|
const quickSearch = useService(QuickSearchService).quickSearch;
|
||||||
const query = useLiveData(quickSearch.query$);
|
const query = useLiveData(quickSearch.query$);
|
||||||
const mode = useLiveData(quickSearch.mode$);
|
|
||||||
// hack: we know that the filtered count is 3 when there is no result (create page & edgeless & append to journal, for mode === 'cmdk')
|
// hack: we know that the filtered count is 3 when there is no result (create page & edgeless & append to journal, for mode === 'cmdk')
|
||||||
const renderNoResult =
|
const renderNoResult = useCommandState(state => state.filtered.count === 3);
|
||||||
useCommandState(state => state.filtered.count === 3) && mode === 'commands';
|
|
||||||
|
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { CommandCategory } from '@affine/core/commands';
|
import type { CommandCategory } from '@affine/core/commands';
|
||||||
import type { DocMode } from '@toeverything/infra';
|
import type { DocMode } from '@toeverything/infra';
|
||||||
|
import type { ReactNode } from 'react';
|
||||||
|
|
||||||
export interface CommandContext {
|
export interface CommandContext {
|
||||||
docMode: DocMode | undefined;
|
docMode: DocMode | undefined;
|
||||||
@@ -11,6 +12,7 @@ export interface CommandContext {
|
|||||||
export interface CMDKCommand {
|
export interface CMDKCommand {
|
||||||
id: string;
|
id: string;
|
||||||
label:
|
label:
|
||||||
|
| ReactNode
|
||||||
| string
|
| string
|
||||||
| {
|
| {
|
||||||
title: string;
|
title: string;
|
||||||
|
|||||||
@@ -553,9 +553,10 @@
|
|||||||
"com.affine.cmdk.affine.color-mode.to": "Change Colour Mode to",
|
"com.affine.cmdk.affine.color-mode.to": "Change Colour Mode to",
|
||||||
"com.affine.cmdk.affine.color-scheme.to": "Change Colour Scheme to",
|
"com.affine.cmdk.affine.color-scheme.to": "Change Colour Scheme to",
|
||||||
"com.affine.cmdk.affine.contact-us": "Contact Us",
|
"com.affine.cmdk.affine.contact-us": "Contact Us",
|
||||||
"com.affine.cmdk.affine.create-new-edgeless-as": "New \"{{keyWord}}\" Edgeless",
|
"com.affine.cmdk.affine.create-new-edgeless-as": "New \"<1>{{keyWord}}</1>\" Edgeless",
|
||||||
"com.affine.cmdk.affine.create-new-page-as": "New \"{{keyWord}}\" Page",
|
"com.affine.cmdk.affine.create-new-page-as": "New \"<1>{{keyWord}}</1>\" Page",
|
||||||
"com.affine.cmdk.affine.create-new-doc-and-insert": "Create \"{{keyWord}}\" Doc and insert",
|
"com.affine.cmdk.affine.create-new-doc-and-insert": "Create \"<1>{{keyWord}}</1>\" Doc and insert",
|
||||||
|
"com.affine.cmdk.affine.insert-link": "Insert this link to the current doc",
|
||||||
"com.affine.cmdk.affine.display-language.to": "Change Display Language to",
|
"com.affine.cmdk.affine.display-language.to": "Change Display Language to",
|
||||||
"com.affine.cmdk.affine.editor.add-to-favourites": "Add to Favourites",
|
"com.affine.cmdk.affine.editor.add-to-favourites": "Add to Favourites",
|
||||||
"com.affine.cmdk.affine.editor.edgeless.presentation-start": "Start Presentation",
|
"com.affine.cmdk.affine.editor.edgeless.presentation-start": "Start Presentation",
|
||||||
|
|||||||
@@ -547,7 +547,7 @@
|
|||||||
"com.affine.cmdk.affine.color-scheme.to": "Changer le thème de couleur pour",
|
"com.affine.cmdk.affine.color-scheme.to": "Changer le thème de couleur pour",
|
||||||
"com.affine.cmdk.affine.contact-us": "Nous contacter",
|
"com.affine.cmdk.affine.contact-us": "Nous contacter",
|
||||||
"com.affine.cmdk.affine.create-new-edgeless-as": "Créer une nouvelle page sans bord sous :",
|
"com.affine.cmdk.affine.create-new-edgeless-as": "Créer une nouvelle page sans bord sous :",
|
||||||
"com.affine.cmdk.affine.create-new-page-as": "Nouveau document \"{{keyWord}}\" ",
|
"com.affine.cmdk.affine.create-new-page-as": "Nouveau document \"<1>{{keyWord}}</1>\" ",
|
||||||
"com.affine.cmdk.affine.display-language.to": "Changer la langue d'affichage pour",
|
"com.affine.cmdk.affine.display-language.to": "Changer la langue d'affichage pour",
|
||||||
"com.affine.cmdk.affine.editor.add-to-favourites": "Ajouter aux Favoris",
|
"com.affine.cmdk.affine.editor.add-to-favourites": "Ajouter aux Favoris",
|
||||||
"com.affine.cmdk.affine.editor.edgeless.presentation-start": "Commencer la Présentation",
|
"com.affine.cmdk.affine.editor.edgeless.presentation-start": "Commencer la Présentation",
|
||||||
|
|||||||
@@ -518,8 +518,8 @@
|
|||||||
"com.affine.cmdk.affine.color-mode.to": "색상 모드를 다음과 같이 변경",
|
"com.affine.cmdk.affine.color-mode.to": "색상 모드를 다음과 같이 변경",
|
||||||
"com.affine.cmdk.affine.color-scheme.to": "색 구성표를 다음과 같이 변경",
|
"com.affine.cmdk.affine.color-scheme.to": "색 구성표를 다음과 같이 변경",
|
||||||
"com.affine.cmdk.affine.contact-us": "Contact Us",
|
"com.affine.cmdk.affine.contact-us": "Contact Us",
|
||||||
"com.affine.cmdk.affine.create-new-edgeless-as": "새 \"{{keyWord}}\" Edgeless",
|
"com.affine.cmdk.affine.create-new-edgeless-as": "새 \"<1>{{keyWord}}</1>\" Edgeless",
|
||||||
"com.affine.cmdk.affine.create-new-page-as": "새 \"{{keyWord}}\" 페이지",
|
"com.affine.cmdk.affine.create-new-page-as": "새 \"<1>{{keyWord}}</1>\" 페이지",
|
||||||
"com.affine.cmdk.affine.display-language.to": "표시 언어를 다음과 같이 변경",
|
"com.affine.cmdk.affine.display-language.to": "표시 언어를 다음과 같이 변경",
|
||||||
"com.affine.cmdk.affine.editor.add-to-favourites": "즐겨찾기에 추가",
|
"com.affine.cmdk.affine.editor.add-to-favourites": "즐겨찾기에 추가",
|
||||||
"com.affine.cmdk.affine.editor.edgeless.presentation-start": "프리젠테이션 시작",
|
"com.affine.cmdk.affine.editor.edgeless.presentation-start": "프리젠테이션 시작",
|
||||||
|
|||||||
@@ -549,8 +549,8 @@
|
|||||||
"com.affine.cmdk.affine.color-mode.to": "Изменить тему на",
|
"com.affine.cmdk.affine.color-mode.to": "Изменить тему на",
|
||||||
"com.affine.cmdk.affine.color-scheme.to": "Изменить цветовую схему на",
|
"com.affine.cmdk.affine.color-scheme.to": "Изменить цветовую схему на",
|
||||||
"com.affine.cmdk.affine.contact-us": "Связаться с нами",
|
"com.affine.cmdk.affine.contact-us": "Связаться с нами",
|
||||||
"com.affine.cmdk.affine.create-new-edgeless-as": "Новый Холст \"{{keyWord}}\"\n",
|
"com.affine.cmdk.affine.create-new-edgeless-as": "Новый Холст \"<1>{{keyWord}}</1>\"\n",
|
||||||
"com.affine.cmdk.affine.create-new-page-as": "Новый документ \"{{keyWord}}\"",
|
"com.affine.cmdk.affine.create-new-page-as": "Новый документ \"<1>{{keyWord}}</1>\"",
|
||||||
"com.affine.cmdk.affine.display-language.to": "Изменить язык интерфейса на",
|
"com.affine.cmdk.affine.display-language.to": "Изменить язык интерфейса на",
|
||||||
"com.affine.cmdk.affine.editor.add-to-favourites": "Добавить в Избранное",
|
"com.affine.cmdk.affine.editor.add-to-favourites": "Добавить в Избранное",
|
||||||
"com.affine.cmdk.affine.editor.edgeless.presentation-start": "Начать презентацию",
|
"com.affine.cmdk.affine.editor.edgeless.presentation-start": "Начать презентацию",
|
||||||
|
|||||||
Reference in New Issue
Block a user