mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 20:38:52 +00:00
fix(plugin): fix left menu behavior
This commit is contained in:
@@ -28,14 +28,11 @@ export const GroupMenu = function ({ editor, hooks }: GroupMenuProps) {
|
||||
|
||||
const handleRootMouseMove = useCallback(
|
||||
async (e: React.MouseEvent<HTMLDivElement>) => {
|
||||
const groupBlockNew =
|
||||
await editor.dragDropManager.getGroupBlockByPoint(
|
||||
new Point(e.clientX, e.clientY)
|
||||
);
|
||||
const groupBlockNew = await editor.getGroupBlockByPoint(
|
||||
new Point(e.clientX, e.clientY)
|
||||
);
|
||||
if (groupBlockNew) {
|
||||
setGroupBlock(groupBlockNew);
|
||||
} else {
|
||||
setGroupBlock(null);
|
||||
}
|
||||
},
|
||||
[editor, setGroupBlock]
|
||||
@@ -59,10 +56,9 @@ export const GroupMenu = function ({ editor, hooks }: GroupMenuProps) {
|
||||
let groupBlockOnDragOver = null;
|
||||
const mousePoint = new Point(e.clientX, e.clientY);
|
||||
if (editor.dragDropManager.isDragGroup(e)) {
|
||||
groupBlockOnDragOver =
|
||||
await editor.dragDropManager.getGroupBlockByPoint(
|
||||
mousePoint
|
||||
);
|
||||
groupBlockOnDragOver = await editor.getGroupBlockByPoint(
|
||||
mousePoint
|
||||
);
|
||||
if (groupBlockOnDragOver?.id === groupBlock?.id) {
|
||||
groupBlockOnDragOver = null;
|
||||
}
|
||||
@@ -83,10 +79,9 @@ export const GroupMenu = function ({ editor, hooks }: GroupMenuProps) {
|
||||
async (e: React.DragEvent<Element>) => {
|
||||
let groupBlockOnDrop = null;
|
||||
if (editor.dragDropManager.isDragGroup(e)) {
|
||||
groupBlockOnDrop =
|
||||
await editor.dragDropManager.getGroupBlockByPoint(
|
||||
new Point(e.clientX, e.clientY)
|
||||
);
|
||||
groupBlockOnDrop = await editor.getGroupBlockByPoint(
|
||||
new Point(e.clientX, e.clientY)
|
||||
);
|
||||
if (groupBlockOnDrop?.id === groupBlock?.id) {
|
||||
groupBlockOnDrop = null;
|
||||
}
|
||||
@@ -95,6 +90,8 @@ export const GroupMenu = function ({ editor, hooks }: GroupMenuProps) {
|
||||
[editor, groupBlock]
|
||||
);
|
||||
|
||||
const handleRootMouseLeave = useCallback(() => setGroupBlock(null), []);
|
||||
|
||||
const handleRootDragEnd = () => {
|
||||
setDragOverGroup(null);
|
||||
};
|
||||
@@ -118,6 +115,11 @@ export const GroupMenu = function ({ editor, hooks }: GroupMenuProps) {
|
||||
.get(HookType.ON_ROOTNODE_DRAG_END)
|
||||
.subscribe(handleRootDragEnd)
|
||||
);
|
||||
sub.add(
|
||||
hooks
|
||||
.get(HookType.ON_ROOTNODE_MOUSE_LEAVE)
|
||||
.subscribe(handleRootMouseLeave)
|
||||
);
|
||||
return () => {
|
||||
sub.unsubscribe();
|
||||
};
|
||||
@@ -127,6 +129,7 @@ export const GroupMenu = function ({ editor, hooks }: GroupMenuProps) {
|
||||
handleRootMouseDown,
|
||||
handleRootDragOver,
|
||||
handleRootDrop,
|
||||
handleRootMouseLeave,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -55,36 +55,36 @@ export function LeftMenu(props: LeftMenuProps) {
|
||||
|
||||
const [menuList, setMenuList] = useState<CascaderItemProps[]>(menu);
|
||||
|
||||
const filter_items = (
|
||||
value: string,
|
||||
menuList: CascaderItemProps[],
|
||||
filterList: CascaderItemProps[]
|
||||
) => {
|
||||
menuList.forEach(item => {
|
||||
if (item?.subItems.length === 0) {
|
||||
if (item.title.toLocaleLowerCase().indexOf(value) !== -1) {
|
||||
filterList.push(item);
|
||||
}
|
||||
} else {
|
||||
filter_items(value, item.subItems || [], filterList);
|
||||
}
|
||||
});
|
||||
};
|
||||
// const filterItems = (
|
||||
// value: string,
|
||||
// menuList: CascaderItemProps[],
|
||||
// filterList: CascaderItemProps[]
|
||||
// ) => {
|
||||
// menuList.forEach(item => {
|
||||
// if (item?.subItems.length === 0) {
|
||||
// if (item.title.toLocaleLowerCase().indexOf(value) !== -1) {
|
||||
// filterList.push(item);
|
||||
// }
|
||||
// } else {
|
||||
// filterItems(value, item.subItems || [], filterList);
|
||||
// }
|
||||
// });
|
||||
// };
|
||||
|
||||
const on_filter = (
|
||||
e: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>
|
||||
) => {
|
||||
const value = e.currentTarget.value;
|
||||
if (!value) {
|
||||
setMenuList(menu);
|
||||
} else {
|
||||
const filterList: CascaderItemProps[] = [];
|
||||
filter_items(value.toLocaleLowerCase(), menu, filterList);
|
||||
setMenuList(
|
||||
filterList.length > 0 ? filterList : [{ title: 'No Result' }]
|
||||
);
|
||||
}
|
||||
};
|
||||
// const on_filter = (
|
||||
// e: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>
|
||||
// ) => {
|
||||
// const value = e.currentTarget.value;
|
||||
// if (!value) {
|
||||
// setMenuList(menu);
|
||||
// } else {
|
||||
// const filterList: CascaderItemProps[] = [];
|
||||
// filter_items(value.toLocaleLowerCase(), menu, filterList);
|
||||
// setMenuList(
|
||||
// filterList.length > 0 ? filterList : [{ title: 'No Result' }]
|
||||
// );
|
||||
// }
|
||||
// };
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -10,8 +10,7 @@ import { Button } from '@toeverything/components/common';
|
||||
import { styled } from '@toeverything/components/ui';
|
||||
|
||||
import { LeftMenu } from './LeftMenu';
|
||||
import { debounce } from '@toeverything/utils';
|
||||
import type { Subject } from 'rxjs';
|
||||
import { distinctUntilChanged, Subject } from 'rxjs';
|
||||
import { HandleChildIcon } from '@toeverything/components/icons';
|
||||
import { MENU_WIDTH } from './menu-config';
|
||||
|
||||
@@ -123,33 +122,24 @@ export const LeftMenuDraggable: FC<LeftMenuProps> = props => {
|
||||
const [block, setBlock] = useState<BlockDomInfo | undefined>();
|
||||
const [line, setLine] = useState<LineInfo | undefined>(undefined);
|
||||
|
||||
const handleDragStart = (event: React.DragEvent<Element>) => {
|
||||
window.addEventListener('dragover', handleDragOverCapture, {
|
||||
capture: true,
|
||||
});
|
||||
|
||||
const onDragStart = async (event: React.DragEvent<Element>) => {
|
||||
editor.dragDropManager.isOnDrag = true;
|
||||
if (block == null) return;
|
||||
setRootRect(editor.container.getBoundingClientRect());
|
||||
const dragImage = await editor.blockHelper.getBlockDragImg(
|
||||
block.blockId
|
||||
);
|
||||
if (dragImage) {
|
||||
event.dataTransfer.setDragImage(dragImage, -50, -10);
|
||||
editor.dragDropManager.setDragBlockInfo(event, block.blockId);
|
||||
}
|
||||
setVisible(false);
|
||||
};
|
||||
onDragStart(event);
|
||||
const handleDragStart = async (event: React.DragEvent<Element>) => {
|
||||
event.stopPropagation();
|
||||
setVisible(false);
|
||||
|
||||
editor.dragDropManager.isOnDrag = true;
|
||||
if (block == null) return;
|
||||
setRootRect(editor.container.getBoundingClientRect());
|
||||
const dragImage = await editor.blockHelper.getBlockDragImg(
|
||||
block.blockId
|
||||
);
|
||||
if (dragImage) {
|
||||
event.dataTransfer.setDragImage(dragImage, -50, -10);
|
||||
editor.dragDropManager.setDragBlockInfo(event, block.blockId);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDragEnd = (event: React.DragEvent<Element>) => {
|
||||
event.preventDefault();
|
||||
window.removeEventListener('dragover', handleDragOverCapture, {
|
||||
capture: true,
|
||||
});
|
||||
setLine(undefined);
|
||||
};
|
||||
|
||||
@@ -161,28 +151,20 @@ export const LeftMenuDraggable: FC<LeftMenuProps> = props => {
|
||||
setAnchorEl(currentTarget);
|
||||
};
|
||||
|
||||
/**
|
||||
* clear line info
|
||||
*/
|
||||
const handleDragOverCapture = debounce((e: MouseEvent) => {
|
||||
const { target } = e;
|
||||
if (
|
||||
target instanceof HTMLElement &&
|
||||
(!target.closest('[data-block-id]') ||
|
||||
!editor.container.contains(target))
|
||||
) {
|
||||
setLine(undefined);
|
||||
}
|
||||
}, 10);
|
||||
|
||||
useEffect(() => {
|
||||
const sub = blockInfo.subscribe(block => {
|
||||
setBlock(block);
|
||||
if (block != null) {
|
||||
setRootRect(editor.container.getBoundingClientRect());
|
||||
setVisible(true);
|
||||
}
|
||||
});
|
||||
const sub = blockInfo
|
||||
.pipe(
|
||||
distinctUntilChanged(
|
||||
(prev, curr) => prev?.blockId === curr?.blockId
|
||||
)
|
||||
)
|
||||
.subscribe(block => {
|
||||
setBlock(block);
|
||||
if (block != null) {
|
||||
setRootRect(editor.container.getBoundingClientRect());
|
||||
setVisible(true);
|
||||
}
|
||||
});
|
||||
return () => sub.unsubscribe();
|
||||
}, [blockInfo, editor]);
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import { domToRect, last, Point } from '@toeverything/utils';
|
||||
export class LeftMenuPlugin extends BasePlugin {
|
||||
private _mousedown?: boolean;
|
||||
private _root?: PluginRenderRoot;
|
||||
private _preBlockId: string;
|
||||
private _hideTimer: number;
|
||||
|
||||
private _blockInfo: Subject<BlockDomInfo | undefined> = new Subject();
|
||||
@@ -23,7 +22,7 @@ export class LeftMenuPlugin extends BasePlugin {
|
||||
public override init(): void {
|
||||
this.sub.add(
|
||||
this.hooks
|
||||
.get(HookType.AFTER_ON_NODE_MOUSE_MOVE)
|
||||
.get(HookType.ON_ROOTNODE_MOUSE_MOVE)
|
||||
.subscribe(this._handleMouseMove)
|
||||
);
|
||||
this.sub.add(
|
||||
@@ -31,11 +30,6 @@ export class LeftMenuPlugin extends BasePlugin {
|
||||
.get(HookType.ON_ROOTNODE_MOUSE_DOWN)
|
||||
.subscribe(this._handleMouseDown)
|
||||
);
|
||||
this.sub.add(
|
||||
this.hooks
|
||||
.get(HookType.ON_ROOTNODE_MOUSE_LEAVE)
|
||||
.subscribe(this._hideLeftMenu)
|
||||
);
|
||||
this.sub.add(
|
||||
this.hooks
|
||||
.get(HookType.ON_ROOTNODE_MOUSE_UP)
|
||||
@@ -46,10 +40,22 @@ export class LeftMenuPlugin extends BasePlugin {
|
||||
.get(HookType.AFTER_ON_NODE_DRAG_OVER)
|
||||
.subscribe(this._handleDragOverBlockNode)
|
||||
);
|
||||
this.sub.add(
|
||||
this.hooks.get(HookType.ON_ROOTNODE_MOUSE_LEAVE).subscribe(() => {
|
||||
this._hideLeftMenu();
|
||||
this._lineInfo.next(undefined);
|
||||
})
|
||||
);
|
||||
this.sub.add(
|
||||
this.hooks.get(HookType.ON_ROOTNODE_DRAG_LEAVE).subscribe(() => {
|
||||
this.editor.dragDropManager.clearDropInfo();
|
||||
this._lineInfo.next(undefined);
|
||||
})
|
||||
);
|
||||
this.sub.add(
|
||||
this.hooks
|
||||
.get(HookType.ON_ROOT_NODE_KEYDOWN)
|
||||
.subscribe(this._handleKeyDown)
|
||||
.subscribe(this._hideLeftMenu)
|
||||
);
|
||||
this.sub.add(
|
||||
this.hooks.get(HookType.ON_ROOTNODE_DROP).subscribe(this._onDrop)
|
||||
@@ -57,7 +63,6 @@ export class LeftMenuPlugin extends BasePlugin {
|
||||
}
|
||||
|
||||
private _onDrop = () => {
|
||||
this._preBlockId = '';
|
||||
this._lineInfo.next(undefined);
|
||||
};
|
||||
private _handleDragOverBlockNode = async ([event, blockInfo]: [
|
||||
@@ -80,10 +85,9 @@ export class LeftMenuPlugin extends BasePlugin {
|
||||
}
|
||||
};
|
||||
|
||||
private _handleMouseMove = async ([e, node]: [
|
||||
React.MouseEvent<HTMLDivElement, MouseEvent>,
|
||||
BlockDomInfo
|
||||
]) => {
|
||||
private _handleMouseMove = async (
|
||||
event: React.MouseEvent<HTMLDivElement, MouseEvent>
|
||||
) => {
|
||||
if (!this._hideTimer) {
|
||||
this._hideTimer = window.setTimeout(() => {
|
||||
if (this._mousedown) {
|
||||
@@ -97,31 +101,40 @@ export class LeftMenuPlugin extends BasePlugin {
|
||||
this._hideLeftMenu();
|
||||
return;
|
||||
}
|
||||
if (node.blockId !== this._preBlockId) {
|
||||
if (node.dom) {
|
||||
const mousePoint = new Point(e.clientX, e.clientY);
|
||||
const children = await (
|
||||
await this.editor.getBlockById(node.blockId)
|
||||
).children();
|
||||
// if mouse point is between the first and last child do not show left menu
|
||||
if (children.length) {
|
||||
const firstChildren = children[0];
|
||||
const lastChildren = last(children);
|
||||
if (firstChildren.dom && lastChildren.dom) {
|
||||
const firstChildrenRect = domToRect(firstChildren.dom);
|
||||
const lastChildrenRect = domToRect(lastChildren.dom);
|
||||
if (
|
||||
firstChildrenRect.top < mousePoint.y &&
|
||||
lastChildrenRect.bottom > mousePoint.y
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const node = await this.editor.getBlockByPoint(
|
||||
new Point(event.clientX, event.clientY)
|
||||
);
|
||||
if (node == null || ignoreBlockTypes.includes(node.type)) {
|
||||
return;
|
||||
}
|
||||
if (node.dom) {
|
||||
const mousePoint = new Point(event.clientX, event.clientY);
|
||||
const children = await (
|
||||
await this.editor.getBlockById(node.id)
|
||||
).children();
|
||||
// if mouse point is between the first and last child do not show left menu
|
||||
if (children.length) {
|
||||
const firstChildren = children[0];
|
||||
const lastChildren = last(children);
|
||||
if (firstChildren.dom && lastChildren.dom) {
|
||||
const firstChildrenRect = domToRect(firstChildren.dom);
|
||||
const lastChildrenRect = domToRect(lastChildren.dom);
|
||||
if (
|
||||
firstChildrenRect.top < mousePoint.y &&
|
||||
lastChildrenRect.bottom > mousePoint.y
|
||||
) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
this._preBlockId = node.blockId;
|
||||
this._showLeftMenu(node);
|
||||
}
|
||||
this._blockInfo.next({
|
||||
blockId: node.id,
|
||||
dom: node.dom,
|
||||
rect: node.dom.getBoundingClientRect(),
|
||||
type: node.type,
|
||||
properties: node.getProperties(),
|
||||
});
|
||||
};
|
||||
|
||||
private _handleMouseUp() {
|
||||
@@ -140,17 +153,6 @@ export class LeftMenuPlugin extends BasePlugin {
|
||||
this._blockInfo.next(undefined);
|
||||
};
|
||||
|
||||
private _handleKeyDown = () => {
|
||||
this._hideLeftMenu();
|
||||
};
|
||||
|
||||
private _showLeftMenu = (blockInfo: BlockDomInfo): void => {
|
||||
if (ignoreBlockTypes.includes(blockInfo.type)) {
|
||||
return;
|
||||
}
|
||||
this._blockInfo.next(blockInfo);
|
||||
};
|
||||
|
||||
protected override _onRender(): void {
|
||||
this._root = new PluginRenderRoot({
|
||||
name: LeftMenuPlugin.pluginName,
|
||||
|
||||
Reference in New Issue
Block a user