feat: Intra-line double link interaction

This commit is contained in:
xiaodong zuo
2022-08-19 09:57:04 +08:00
parent 438d814d49
commit f0f60654e8
3 changed files with 38 additions and 29 deletions

View File

@@ -20,6 +20,7 @@ export const DoubleLinkComponent = ({ attributes, children, element }: any) => {
<PagesIcon style={{ verticalAlign: 'middle', height: '20px' }} /> <PagesIcon style={{ verticalAlign: 'middle', height: '20px' }} />
<a <a
{...attributes} {...attributes}
style={{ cursor: 'pointer' }}
href={`/${element.workspaceId}/${element.blockId}`} href={`/${element.workspaceId}/${element.blockId}`}
> >
<span onClick={handleClickLinkText}>{children}</span> <span onClick={handleClickLinkText}>{children}</span>

View File

@@ -599,6 +599,10 @@ class SlateUtils {
const textChildren: Text[] = []; const textChildren: Text[] = [];
for (const child of fragmentChildren) { for (const child of fragmentChildren) {
if ((child as any).type === 'link') {
textChildren.push(child as Text);
continue;
}
if (!('text' in child)) { if (!('text' in child)) {
console.error('Debug information:', point1, point2, fragment); console.error('Debug information:', point1, point2, fragment);
throw new Error('Fragment exists nested!'); throw new Error('Fragment exists nested!');

View File

@@ -11,7 +11,6 @@ import {
} from '@toeverything/components/ui'; } from '@toeverything/components/ui';
import { services } from '@toeverything/datasource/db-service'; import { services } from '@toeverything/datasource/db-service';
import { HookType, PluginHooks, Virgo } from '@toeverything/framework/virgo'; import { HookType, PluginHooks, Virgo } from '@toeverything/framework/virgo';
import { getPageId } from '@toeverything/utils';
import React, { import React, {
ChangeEvent, ChangeEvent,
useCallback, useCallback,
@@ -20,12 +19,13 @@ import React, {
useRef, useRef,
useState, useState,
} from 'react'; } from 'react';
import { useParams } from 'react-router-dom';
import { QueryBlocks, QueryResult } from '../../search'; import { QueryBlocks, QueryResult } from '../../search';
import { DoubleLinkMenuContainer } from './Container'; import { DoubleLinkMenuContainer } from './Container';
const ADD_NEW_SUB_PAGE = 'AddNewSubPage'; const ADD_NEW_SUB_PAGE = 'AddNewSubPage';
const ADD_NEW_PAGE = 'AddNewPage'; const ADD_NEW_PAGE = 'AddNewPage';
const ARRAY_KEYS = ['ArrowRight', 'ArrowLeft', 'ArrowUp', 'ArrowDown']; const ARRAY_CODES = ['ArrowRight', 'ArrowLeft', 'ArrowUp', 'ArrowDown'];
export type DoubleLinkMenuProps = { export type DoubleLinkMenuProps = {
editor: Virgo; editor: Virgo;
@@ -44,6 +44,7 @@ export const DoubleLinkMenu = ({
hooks, hooks,
style, style,
}: DoubleLinkMenuProps) => { }: DoubleLinkMenuProps) => {
const { page_id: curPageId } = useParams();
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [anchorEl, setAnchorEl] = useState(null); const [anchorEl, setAnchorEl] = useState(null);
const dialogRef = useRef<HTMLDivElement>(); const dialogRef = useRef<HTMLDivElement>();
@@ -120,9 +121,12 @@ export const DoubleLinkMenu = ({
useEffect(() => { useEffect(() => {
const text = inAddNewPage ? filterText : searchText; const text = inAddNewPage ? filterText : searchText;
QueryBlocks(editor, text, result => { QueryBlocks(editor, text, result => {
if (!inAddNewPage) {
result = result.filter(item => item.id !== curPageId);
}
setSearchResultBlocks(result); setSearchResultBlocks(result);
}); });
}, [editor, searchText, filterText, inAddNewPage]); }, [editor, searchText, filterText, inAddNewPage, curPageId]);
const hideMenu = useCallback(() => { const hideMenu = useCallback(() => {
setIsOpen(false); setIsOpen(false);
@@ -133,23 +137,31 @@ export const DoubleLinkMenu = ({
const searchChange = useCallback( const searchChange = useCallback(
async (event: React.KeyboardEvent<HTMLDivElement>) => { async (event: React.KeyboardEvent<HTMLDivElement>) => {
if (ARRAY_KEYS.includes(event.key)) { if (ARRAY_CODES.includes(event.code)) {
return; return;
} }
if (event.code === 'Backspace') {
const searchText =
editor.blockHelper.getDoubleLinkSearchSlashText(curBlockId);
if (!searchText || searchText === '[[') {
hideMenu();
event.preventDefault();
event.stopPropagation();
return;
}
}
const { type, anchorNode } = editor.selection.currentSelectInfo; const { type, anchorNode } = editor.selection.currentSelectInfo;
if ( if (
type === 'Range' && !isOpen ||
anchorNode && (type === 'Range' &&
editor.blockHelper.isSelectionCollapsed(anchorNode.id) anchorNode &&
anchorNode.id !== curBlockId &&
editor.blockHelper.isSelectionCollapsed(anchorNode.id))
) { ) {
const text = editor.blockHelper.getBlockTextBeforeSelection( const text = editor.blockHelper.getBlockTextBeforeSelection(
anchorNode.id anchorNode.id
); );
if (text.endsWith('[[')) { if (text.endsWith('[[')) {
if (event.key === 'Backspace') {
hideMenu();
return;
}
editor.blockHelper.removeDoubleLinkSearchSlash(curBlockId); editor.blockHelper.removeDoubleLinkSearchSlash(curBlockId);
setCurBlockId(anchorNode.id); setCurBlockId(anchorNode.id);
setSearchText(''); setSearchText('');
@@ -211,26 +223,18 @@ export const DoubleLinkMenu = ({
if (event.code === 'Escape') { if (event.code === 'Escape') {
hideMenu(); hideMenu();
} }
const { type, anchorNode } = editor.selection.currentSelectInfo;
if ( if (event.code === 'Backspace') {
type === 'Range' && const searchText =
anchorNode && editor.blockHelper.getDoubleLinkSearchSlashText(curBlockId);
editor.blockHelper.isSelectionCollapsed(anchorNode.id) if (!searchText || searchText === '[[') {
) { event.preventDefault();
const text = editor.blockHelper.getBlockTextBeforeSelection( event.stopPropagation();
anchorNode.id return;
);
if (text.endsWith('[[')) {
if (event.key === 'Backspace') {
event.preventDefault();
event.stopPropagation();
hideMenu();
return;
}
} }
} }
}, },
[hideMenu, editor, isOpen] [hideMenu, editor, isOpen, curBlockId]
); );
useEffect(() => { useEffect(() => {
@@ -294,7 +298,7 @@ export const DoubleLinkMenu = ({
return; return;
} }
if (id === ADD_NEW_SUB_PAGE) { if (id === ADD_NEW_SUB_PAGE) {
const pageId = await addSubPage(getPageId()); const pageId = await addSubPage(curPageId);
insertDoubleLink(pageId); insertDoubleLink(pageId);
return; return;
} }