Merge pull request #279 from toeverything/refactor/clean

Refactor/clean
This commit is contained in:
mitsuha(XiWen TU) 2022-08-17 21:01:36 +08:00 committed by GitHub
commit 91fa616942
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 106 additions and 95 deletions

View File

@ -14,7 +14,7 @@ import { CreateView } from '@toeverything/framework/virgo';
import { BlockContainer } from '../../components/BlockContainer';
import { IndentWrapper } from '../../components/IndentWrapper';
import { TextManage } from '../../components/text-manage';
import { tabBlock } from '../../utils/indent';
import { dedentBlock, tabBlock } from '../../utils/indent';
interface CreateTextView extends CreateView {
// TODO: need to optimize
containerClassName?: string;
@ -115,7 +115,19 @@ export const TextView = ({
return false;
}
const preParent = await parentBlock.previousSibling();
// The parent block is group block or is the root block.
// Merge block to previous sibling.
//
// - group/root <- parent block
// - text1 <- preNode
// - text2 <- press backspace before target block
// - children
//
// ---
//
// - group/root
// - text1text2 <- merge block to previous sibling
// - children <- children should switch parent block
if (
Protocol.Block.Type.group === parentBlock.type ||
editor.getRootBlockId() === parentBlock.id
@ -130,10 +142,7 @@ export const TextView = ({
block.id,
'end'
);
if (
block.getProperty('text').value[0] &&
block.getProperty('text').value[0]?.text !== ''
) {
if (!block.blockProvider?.isEmpty()) {
const value = [
...preNode.getProperty('text').value,
...block.getProperty('text').value,
@ -145,12 +154,13 @@ export const TextView = ({
await preNode.append(...children);
await block.remove();
} else {
// If not pre node, block should be merged to the parent block
// TODO: point does not clear
await editor.selectionManager.activePreviousNode(
block.id,
'start'
);
if (block.blockProvider.isEmpty()) {
if (block.blockProvider?.isEmpty()) {
await block.remove();
const parentChild = await parentBlock.children();
if (
@ -158,6 +168,8 @@ export const TextView = ({
Protocol.Block.Type.group &&
!parentChild.length
) {
const preParent =
await parentBlock.previousSibling();
await editor.selectionManager.setSelectedNodesIds(
[preParent?.id ?? editor.getRootBlockId()]
);
@ -198,17 +210,9 @@ export const TextView = ({
await parentBlock.remove();
}
return true;
} else {
const nextNodes = await block.nextSiblings();
for (const nextNode of nextNodes) {
await nextNode.remove();
}
block.append(...nextNodes);
editor.commands.blockCommands.moveBlockAfter(
block.id,
parentBlock.id
);
}
dedentBlock(editor, block);
return true;
}
);

View File

@ -1,6 +1,6 @@
import {
type BlockEditor,
supportChildren,
type BlockEditor,
} from '@toeverything/components/editor-core';
import { Protocol } from '@toeverything/datasource/db-service';
import { AsyncBlock } from '@toeverything/framework/virgo';
@ -81,7 +81,7 @@ const indentBlock = async (block: TodoAsyncBlock) => {
* [ ]
* ```
*/
const dedentBlock = async (editor: BlockEditor, block: AsyncBlock) => {
export const dedentBlock = async (editor: BlockEditor, block: AsyncBlock) => {
if (editor.getRootBlockId() === block.id) {
return false;
}

View File

@ -1,4 +1,5 @@
/* eslint-disable max-lines */
import { Protocol } from '@toeverything/datasource/db-service';
import { domToRect, Point } from '@toeverything/utils';
import { AsyncBlock } from '../..';
import { GridDropType } from '../commands/types';
@ -6,7 +7,6 @@ import { Editor } from '../editor';
import { BlockDropPlacement, GroupDirection } from '../types';
// TODO: Evaluate implementing custom events with Rxjs
import EventEmitter from 'eventemitter3';
import { Protocol } from '@toeverything/datasource/db-service';
enum DragType {
dragBlock = 'dragBlock',
@ -281,6 +281,10 @@ export class DragDropManager {
this._editor.getRootBlockId()
);
let direction = BlockDropPlacement.none;
if (!rootBlock || !rootBlock.dom) {
console.warn('Can not find dom bind with block', rootBlock);
return;
}
const rootBlockRect = domToRect(rootBlock.dom);
let targetBlock: AsyncBlock | undefined;
let typesInfo = {
@ -303,6 +307,10 @@ export class DragDropManager {
if (direction !== BlockDropPlacement.none) {
const blockList = await this._editor.getBlockListByLevelOrder();
targetBlock = blockList.find(block => {
if (!block.dom) {
console.warn('Can not find dom bind with block', block);
return false;
}
const domRect = domToRect(block.dom);
const pointChecker =
direction === BlockDropPlacement.outerLeft

View File

@ -1,15 +1,16 @@
/* eslint-disable max-lines */
import {
debounce,
domToRect,
getBlockIdByDom,
last,
Point,
Rect,
last,
without,
debounce,
getBlockIdByDom,
} from '@toeverything/utils';
import EventEmitter from 'eventemitter3';
import { Protocol } from '@toeverything/datasource/db-service';
import { BlockEditor } from '../..';
import { AsyncBlock } from '../block';
import { VirgoSelection } from '../types';
@ -18,19 +19,17 @@ import {
changeEventName,
CursorTypes,
IdList,
SelectBlock,
selectEndEventName,
SelectEventCallbackTypes,
SelectEventTypes,
SelectInfo,
SelectionSettings,
SelectionSettingsMap,
SelectionTypes,
SelectPosition,
SelectBlock,
SelectInfo,
} from './types';
import { isLikeBlockListIds } from './utils';
import { Protocol } from '@toeverything/datasource/db-service';
import { Editor } from 'slate';
// IMP: maybe merge active and select into single function
export type SelectionInfo = InstanceType<
@ -336,12 +335,12 @@ export class SelectionManager implements VirgoSelection {
});
for await (const childBlock of selectableChildren) {
const { dom } = childBlock;
if (dom && selectionRect.isIntersect(domToRect(dom))) {
selectedNodes.push(childBlock);
}
if (!dom) {
console.warn('can not find dom bind with block');
}
if (dom && selectionRect.isIntersect(domToRect(dom))) {
selectedNodes.push(childBlock);
}
}
// if just only has one selected maybe select the children
if (selectedNodes.length === 1) {
@ -1063,10 +1062,10 @@ export class SelectionManager implements VirgoSelection {
index: number,
blockId: string
): Promise<void> {
let preRang = document.createRange();
const preRang = document.createRange();
preRang.setStart(nowRange.startContainer, index);
preRang.setEnd(nowRange.endContainer, index);
let prePosition = preRang.getClientRects().item(0);
const prePosition = preRang.getClientRects().item(0);
this.activeNodeByNodeId(
blockId,
new Point(prePosition.left, prePosition.bottom)

View File

@ -9,10 +9,10 @@ import {
BlockDecoration,
MapOperation,
} from '@toeverything/datasource/jwt';
import { cloneDeep } from '@toeverything/utils';
import type { EventData } from '../block';
import { AsyncBlock } from '../block';
import type { Editor } from '../editor';
import { cloneDeep } from '@toeverything/utils';
import { SelectBlock } from '../selection';
export interface CreateView {
@ -114,7 +114,21 @@ export abstract class BaseView {
// Whether the component is empty
isEmpty(block: AsyncBlock): boolean {
const text = block.getProperty('text');
return !text?.value?.[0]?.text;
const result = !text?.value?.[0]?.text;
// Assert that the text is really empty
if (
result &&
block.getProperty('text')?.value.some(content => content.text)
) {
console.warn(
'Assertion isEmpty error! The block has an empty start fragment, but it is not empty',
block
);
}
// Assert end
return result;
}
getSelProperties(block: AsyncBlock, selectInfo: any): DefaultColumnsValue {

View File

@ -1,15 +1,15 @@
import { HookType, BlockDropPlacement } from '@toeverything/framework/virgo';
import { StrictMode } from 'react';
import { BasePlugin } from '../../base-plugin';
import { ignoreBlockTypes } from './menu-config';
import {
LineInfoSubject,
LeftMenuDraggable,
BlockDomInfo,
} from './LeftMenuDraggable';
import { PluginRenderRoot } from '../../utils';
import { Subject, throttleTime } from 'rxjs';
import { BlockDropPlacement, HookType } from '@toeverything/framework/virgo';
import { domToRect, last, Point } from '@toeverything/utils';
import { StrictMode } from 'react';
import { Subject, throttleTime } from 'rxjs';
import { BasePlugin } from '../../base-plugin';
import { PluginRenderRoot } from '../../utils';
import {
BlockDomInfo,
LeftMenuDraggable,
LineInfoSubject,
} from './LeftMenuDraggable';
import { ignoreBlockTypes } from './menu-config';
const DRAG_THROTTLE_DELAY = 60;
export class LeftMenuPlugin extends BasePlugin {
private _mousedown?: boolean;
@ -111,6 +111,10 @@ export class LeftMenuPlugin extends BasePlugin {
block.dom,
block.id
);
if (!targetBlock.dom) {
console.warn('Can not find dom bind with block', targetBlock);
return;
}
this._lineInfo.next({
direction,
blockInfo: {

View File

@ -3,9 +3,7 @@ import type {
MouseEventHandler,
PropsWithChildren,
} from 'react';
import { cx } from '../clsx';
import { styled } from '../styled';
import { buttonStatus } from './constants';
/* Temporary solution, needs to be adjusted */
const SIZE_SMALL = 'small' as const;
@ -29,13 +27,18 @@ const SIZE_CONFIG = {
type SizeType = keyof typeof SIZE_CONFIG;
interface IconButtonProps {
type IconButtonContainerProps = {
size?: SizeType;
hoverColor?: string; // CSSProperties['backgroundColor'];
backgroundColor?: string; // CSSProperties['backgroundColor'];
disabled?: boolean;
};
interface IconButtonProps extends IconButtonContainerProps {
onClick?: MouseEventHandler;
disabled?: boolean;
style?: CSSProperties;
className?: string;
size?: SizeType;
hoverColor?: string;
}
export const IconButton = ({
@ -50,55 +53,40 @@ export const IconButton = ({
{...props}
onClick={disabled ? undefined : onClick}
disabled={disabled}
className={cx({ [buttonStatus.disabled]: disabled }, className)}
>
{children}
</Container>
);
};
const Container = styled('button')<{
size?: SizeType;
hoverColor?: string;
}>(({ theme, size = SIZE_MIDDLE, hoverColor }) => {
const { iconSize, areaSize } = SIZE_CONFIG[size];
const Container = styled('button')<IconButtonContainerProps>(
({ theme, size = SIZE_MIDDLE, hoverColor, backgroundColor, disabled }) => {
const { iconSize, areaSize } = SIZE_CONFIG[size];
return {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
width: areaSize,
height: areaSize,
backgroundColor: 'transparent',
color: theme.affine.palette.icons,
padding: theme.affine.spacing.iconPadding,
borderRadius: '3px',
'& svg': {
width: iconSize,
height: iconSize,
return {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
},
width: areaSize,
height: areaSize,
backgroundColor: backgroundColor ?? 'transparent',
color: theme.affine.palette.icons,
padding: theme.affine.spacing.iconPadding,
borderRadius: '3px',
'&:hover': {
backgroundColor: hoverColor || theme.affine.palette.hover,
},
'& svg': {
width: iconSize,
height: iconSize,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
},
[`&${buttonStatus.hover}`]: {
backgroundColor: theme.affine.palette.hover,
},
'&:hover': {
backgroundColor: hoverColor || theme.affine.palette.hover,
},
'&:focus': {
color: theme.affine.palette.primary,
},
[`&.${buttonStatus.focus}`]: {
color: theme.affine.palette.primary,
},
[`&${buttonStatus.disabled}`]: {
cursor: 'not-allowed',
},
};
});
...(disabled ? { cursor: 'not-allowed' } : {}),
};
}
);

View File

@ -1,6 +0,0 @@
export const buttonStatus = {
hover: '.hover',
focus: '.focus',
active: '.focus',
disabled: '.disabled',
};