mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-11 23:26:30 +08:00
Merge to master (#435)
* Fix/venus spanish (#423) fix: update venus spanish language Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com> * fix: can not convert url text to link after paste * fix: double link icon size error * feat(code): enhance markdown parse code * fix(code): add robust * fix: remove special menu * chore: clean code * fix: ime with command menu * fix(code): langs[lang] is not a function * fix: can't add image and delete more action button (#430) * feat: add zh_Hant for venus (#431) * fix: lang select in code block is insanity * GitHub Doc Updates (#421) * Update types-of-contributions.md * Update README.md Tidy up links section * fix: inline menu position (#433) Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com> Co-authored-by: QiShaoXuan <qishaoxuan777@gmail.com> Co-authored-by: tzhangchi <terry.zhangchi@outlook.com> Co-authored-by: lawvs <18554747+lawvs@users.noreply.github.com> Co-authored-by: DiamondThree <diamond.shx@gmail.com> Co-authored-by: CJSS <CJSS@users.noreply.github.com> Co-authored-by: Qi <474021214@qq.com>
This commit is contained in:
@@ -1,9 +1,8 @@
|
||||
import { StrictMode } from 'react';
|
||||
import { createRoot, type Root } from 'react-dom/client';
|
||||
|
||||
import { BasePlugin } from '../../base-plugin';
|
||||
import { CommandMenu } from './Menu';
|
||||
import { PluginRenderRoot } from '../../utils';
|
||||
import { CommandMenu } from './Menu';
|
||||
|
||||
const PLUGIN_NAME = 'command-menu';
|
||||
|
||||
|
||||
@@ -1,28 +1,24 @@
|
||||
import React, {
|
||||
useEffect,
|
||||
useState,
|
||||
useMemo,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import style9 from 'style9';
|
||||
|
||||
import { BlockFlavorKeys } from '@toeverything/datasource/db-service';
|
||||
import { Virgo, PluginHooks, HookType } from '@toeverything/framework/virgo';
|
||||
import {
|
||||
CommonList,
|
||||
CommonListItem,
|
||||
commonListContainer,
|
||||
CommonListItem,
|
||||
} from '@toeverything/components/common';
|
||||
import { BlockFlavorKeys } from '@toeverything/datasource/db-service';
|
||||
import { HookType, PluginHooks, Virgo } from '@toeverything/framework/virgo';
|
||||
import { domToRect } from '@toeverything/utils';
|
||||
|
||||
import { MenuCategories } from './Categories';
|
||||
import { menuItemsMap, CommandMenuCategories } from './config';
|
||||
import { styled } from '@toeverything/components/ui';
|
||||
import { QueryResult } from '../../search';
|
||||
import {
|
||||
MuiClickAwayListener as ClickAwayListener,
|
||||
styled,
|
||||
} from '@toeverything/components/ui';
|
||||
import { MenuCategories } from './Categories';
|
||||
import { CommandMenuCategories, menuItemsMap } from './config';
|
||||
|
||||
const RootContainer = styled('div')(({ theme }) => {
|
||||
return {
|
||||
@@ -134,59 +130,75 @@ export const CommandMenuContainer = ({
|
||||
|
||||
const handleClickUp = useCallback(
|
||||
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
if (isShow && types && event.code === 'ArrowUp') {
|
||||
event.preventDefault();
|
||||
if (!currentItem && types.length) {
|
||||
setCurrentItem(types[types.length - 1]);
|
||||
}
|
||||
if (currentItem) {
|
||||
const idx = types.indexOf(currentItem);
|
||||
if (idx > 0) {
|
||||
setNeedCheckIntoView(true);
|
||||
setCurrentItem(types[idx - 1]);
|
||||
}
|
||||
event.preventDefault();
|
||||
if (!currentItem && types.length) {
|
||||
setCurrentItem(types[types.length - 1]);
|
||||
}
|
||||
if (currentItem) {
|
||||
const idx = types.indexOf(currentItem);
|
||||
if (idx > 0) {
|
||||
setNeedCheckIntoView(true);
|
||||
setCurrentItem(types[idx - 1]);
|
||||
}
|
||||
}
|
||||
},
|
||||
[isShow, types, currentItem]
|
||||
[types, currentItem]
|
||||
);
|
||||
|
||||
const handleClickDown = useCallback(
|
||||
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
if (isShow && types && event.code === 'ArrowDown') {
|
||||
event.preventDefault();
|
||||
if (!currentItem && types.length) {
|
||||
setCurrentItem(types[0]);
|
||||
}
|
||||
if (currentItem) {
|
||||
const idx = types.indexOf(currentItem);
|
||||
if (idx < types.length - 1) {
|
||||
setNeedCheckIntoView(true);
|
||||
setCurrentItem(types[idx + 1]);
|
||||
}
|
||||
event.preventDefault();
|
||||
if (!currentItem && types.length) {
|
||||
setCurrentItem(types[0]);
|
||||
}
|
||||
if (currentItem) {
|
||||
const idx = types.indexOf(currentItem);
|
||||
if (idx < types.length - 1) {
|
||||
setNeedCheckIntoView(true);
|
||||
setCurrentItem(types[idx + 1]);
|
||||
}
|
||||
}
|
||||
},
|
||||
[isShow, types, currentItem]
|
||||
[types, currentItem]
|
||||
);
|
||||
|
||||
const handleClickEnter = useCallback(
|
||||
async (event: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
if (isShow && event.code === 'Enter' && currentItem) {
|
||||
event.preventDefault();
|
||||
onSelected && onSelected(currentItem);
|
||||
}
|
||||
event.preventDefault();
|
||||
onSelected && onSelected(currentItem);
|
||||
},
|
||||
[isShow, currentItem, onSelected]
|
||||
[currentItem, onSelected]
|
||||
);
|
||||
|
||||
const handleKeyDown = useCallback(
|
||||
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
handleClickUp(event);
|
||||
handleClickDown(event);
|
||||
handleClickEnter(event);
|
||||
if (!isShow) {
|
||||
return;
|
||||
}
|
||||
if (event.nativeEvent.isComposing) {
|
||||
return;
|
||||
}
|
||||
if (types && event.code === 'ArrowUp') {
|
||||
handleClickUp(event);
|
||||
return;
|
||||
}
|
||||
if (types && event.code === 'ArrowDown') {
|
||||
handleClickDown(event);
|
||||
return;
|
||||
}
|
||||
if (event.code === 'Enter' && currentItem) {
|
||||
handleClickEnter(event);
|
||||
return;
|
||||
}
|
||||
},
|
||||
[handleClickUp, handleClickDown, handleClickEnter]
|
||||
[
|
||||
isShow,
|
||||
types,
|
||||
currentItem,
|
||||
handleClickUp,
|
||||
handleClickDown,
|
||||
handleClickEnter,
|
||||
]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -212,7 +212,7 @@ export const CommandMenu = ({ editor, hooks, style }: CommandMenuProps) => {
|
||||
const handleSelected = async (type: BlockFlavorKeys | string) => {
|
||||
const text = await editor.commands.textCommands.getBlockText(blockId);
|
||||
const block = await editor.getBlockById(blockId);
|
||||
let textValue = block.getProperty('text').value;
|
||||
const textValue = block.getProperty('text').value;
|
||||
editor.blockHelper.removeSearchSlash(blockId, true);
|
||||
if (type.startsWith('Virgo')) {
|
||||
const handler =
|
||||
@@ -261,23 +261,21 @@ export const CommandMenu = ({ editor, hooks, style }: CommandMenuProps) => {
|
||||
>
|
||||
{show ? (
|
||||
<MuiClickAwayListener onClickAway={handleClickAway}>
|
||||
<div>
|
||||
<CommandMenuContainer
|
||||
editor={editor}
|
||||
hooks={hooks}
|
||||
style={{
|
||||
...commandMenuPosition,
|
||||
...style,
|
||||
}}
|
||||
isShow={show}
|
||||
blockId={blockId}
|
||||
onSelected={handleSelected}
|
||||
onclose={handleClose}
|
||||
searchBlocks={searchBlocks}
|
||||
types={types}
|
||||
categories={categories}
|
||||
/>
|
||||
</div>
|
||||
<CommandMenuContainer
|
||||
editor={editor}
|
||||
hooks={hooks}
|
||||
style={{
|
||||
...commandMenuPosition,
|
||||
...style,
|
||||
}}
|
||||
isShow={show}
|
||||
blockId={blockId}
|
||||
onSelected={handleSelected}
|
||||
onclose={handleClose}
|
||||
searchBlocks={searchBlocks}
|
||||
types={types}
|
||||
categories={categories}
|
||||
/>
|
||||
</MuiClickAwayListener>
|
||||
) : (
|
||||
<></>
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
import {
|
||||
HeadingOneIcon,
|
||||
HeadingTwoIcon,
|
||||
HeadingThreeIcon,
|
||||
ToDoIcon,
|
||||
NumberIcon,
|
||||
BulletIcon,
|
||||
CodeIcon,
|
||||
TextIcon,
|
||||
PagesIcon,
|
||||
ImageIcon,
|
||||
FileIcon,
|
||||
QuoteIcon,
|
||||
CalloutIcon,
|
||||
CodeIcon,
|
||||
DividerIcon,
|
||||
FigmaIcon,
|
||||
YoutubeIcon,
|
||||
EmbedIcon,
|
||||
FigmaIcon,
|
||||
FileIcon,
|
||||
HeadingOneIcon,
|
||||
HeadingThreeIcon,
|
||||
HeadingTwoIcon,
|
||||
ImageIcon,
|
||||
NumberIcon,
|
||||
QuoteIcon,
|
||||
TextIcon,
|
||||
ToDoIcon,
|
||||
YoutubeIcon,
|
||||
} from '@toeverything/components/icons';
|
||||
import { SvgIconProps } from '@toeverything/components/ui';
|
||||
import { Virgo } from '@toeverything/framework/virgo';
|
||||
import { BlockFlavorKeys, Protocol } from '@toeverything/datasource/db-service';
|
||||
import { Virgo } from '@toeverything/framework/virgo';
|
||||
import { without } from '@toeverything/utils';
|
||||
|
||||
export enum CommandMenuCategories {
|
||||
@@ -68,11 +67,12 @@ export const menuItemsMap: {
|
||||
type: Protocol.Block.Type.text,
|
||||
icon: TextIcon,
|
||||
},
|
||||
{
|
||||
text: 'Page',
|
||||
type: 'page',
|
||||
icon: PagesIcon,
|
||||
},
|
||||
// the Page block should not be inserted
|
||||
// {
|
||||
// text: 'Page',
|
||||
// type: Protocol.Block.Type.page,
|
||||
// icon: PagesIcon,
|
||||
// },
|
||||
{
|
||||
text: 'Heading 1',
|
||||
type: Protocol.Block.Type.heading1,
|
||||
@@ -91,7 +91,7 @@ export const menuItemsMap: {
|
||||
],
|
||||
[CommandMenuCategories.lists]: [
|
||||
{
|
||||
text: 'To do',
|
||||
text: 'Todo',
|
||||
type: Protocol.Block.Type.todo,
|
||||
icon: ToDoIcon,
|
||||
},
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { MuiGrow as Grow, styled } from '@toeverything/components/ui';
|
||||
import { Protocol } from '@toeverything/datasource/db-service';
|
||||
import {
|
||||
MuiClickAwayListener as ClickAwayListener,
|
||||
MuiGrow as Grow,
|
||||
styled,
|
||||
} from '@toeverything/components/ui';
|
||||
|
||||
import { Virgo, SelectionInfo } from '@toeverything/framework/virgo';
|
||||
import { SelectionInfo, Virgo } from '@toeverything/framework/virgo';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { InlineMenuToolbar } from './Toolbar';
|
||||
|
||||
export type InlineMenuContainerProps = {
|
||||
@@ -47,11 +42,18 @@ export const InlineMenuContainer = ({ editor }: InlineMenuContainerProps) => {
|
||||
|
||||
// This is relative to window
|
||||
const rect = browserSelection.getRangeAt(0).getBoundingClientRect();
|
||||
const { top, left } = editor.container.getBoundingClientRect();
|
||||
|
||||
const { top, left, right } =
|
||||
editor.container.getBoundingClientRect();
|
||||
let menuLeft = rect.left - left;
|
||||
if (right - rect.right < 500) {
|
||||
// If the inline-menu is further away from the right than the button itself, a scroll bar will appear
|
||||
menuLeft -= 500;
|
||||
}
|
||||
setSelectionInfo(info);
|
||||
setShowMenu(true);
|
||||
setContainerStyle({
|
||||
left: rect.left - left,
|
||||
left: menuLeft,
|
||||
top: rect.top - top - 64,
|
||||
});
|
||||
});
|
||||
@@ -89,6 +91,6 @@ const ToolbarContainer = styled('div')(({ theme }) => ({
|
||||
alignItems: 'center',
|
||||
padding: '0 12px',
|
||||
borderRadius: '10px',
|
||||
boxShadow: theme.affine.shadows.shadow1,
|
||||
boxShadow: theme.affine.shadows.shadow3,
|
||||
backgroundColor: '#fff',
|
||||
}));
|
||||
|
||||
@@ -22,7 +22,6 @@ import {
|
||||
HeadingTwoIcon,
|
||||
ImageIcon,
|
||||
LinkIcon,
|
||||
MoreIcon,
|
||||
NumberIcon,
|
||||
PagesIcon,
|
||||
QuoteIcon,
|
||||
@@ -827,13 +826,13 @@ export const getInlineMenuData = ({
|
||||
nameKey: inlineMenuNamesKeys.backlinks,
|
||||
onClick: common_handler_for_inline_menu,
|
||||
},
|
||||
{
|
||||
type: INLINE_MENU_UI_TYPES.icon,
|
||||
icon: MoreIcon,
|
||||
name: inlineMenuNames.moreActions,
|
||||
nameKey: inlineMenuNamesKeys.moreActions,
|
||||
onClick: common_handler_for_inline_menu,
|
||||
},
|
||||
// {
|
||||
// type: INLINE_MENU_UI_TYPES.icon,
|
||||
// icon: MoreIcon,
|
||||
// name: inlineMenuNames.moreActions,
|
||||
// nameKey: inlineMenuNamesKeys.moreActions,
|
||||
// onClick: common_handler_for_inline_menu,
|
||||
// },
|
||||
];
|
||||
|
||||
return inlineMenuData.filter(item => Boolean(item));
|
||||
|
||||
Reference in New Issue
Block a user