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 { BlockContainer } from '../../components/BlockContainer';
import { IndentWrapper } from '../../components/IndentWrapper'; import { IndentWrapper } from '../../components/IndentWrapper';
import { TextManage } from '../../components/text-manage'; import { TextManage } from '../../components/text-manage';
import { tabBlock } from '../../utils/indent'; import { dedentBlock, tabBlock } from '../../utils/indent';
interface CreateTextView extends CreateView { interface CreateTextView extends CreateView {
// TODO: need to optimize // TODO: need to optimize
containerClassName?: string; containerClassName?: string;
@ -115,7 +115,19 @@ export const TextView = ({
return false; 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 ( if (
Protocol.Block.Type.group === parentBlock.type || Protocol.Block.Type.group === parentBlock.type ||
editor.getRootBlockId() === parentBlock.id editor.getRootBlockId() === parentBlock.id
@ -130,10 +142,7 @@ export const TextView = ({
block.id, block.id,
'end' 'end'
); );
if ( if (!block.blockProvider?.isEmpty()) {
block.getProperty('text').value[0] &&
block.getProperty('text').value[0]?.text !== ''
) {
const value = [ const value = [
...preNode.getProperty('text').value, ...preNode.getProperty('text').value,
...block.getProperty('text').value, ...block.getProperty('text').value,
@ -145,12 +154,13 @@ export const TextView = ({
await preNode.append(...children); await preNode.append(...children);
await block.remove(); await block.remove();
} else { } else {
// If not pre node, block should be merged to the parent block
// TODO: point does not clear // TODO: point does not clear
await editor.selectionManager.activePreviousNode( await editor.selectionManager.activePreviousNode(
block.id, block.id,
'start' 'start'
); );
if (block.blockProvider.isEmpty()) { if (block.blockProvider?.isEmpty()) {
await block.remove(); await block.remove();
const parentChild = await parentBlock.children(); const parentChild = await parentBlock.children();
if ( if (
@ -158,6 +168,8 @@ export const TextView = ({
Protocol.Block.Type.group && Protocol.Block.Type.group &&
!parentChild.length !parentChild.length
) { ) {
const preParent =
await parentBlock.previousSibling();
await editor.selectionManager.setSelectedNodesIds( await editor.selectionManager.setSelectedNodesIds(
[preParent?.id ?? editor.getRootBlockId()] [preParent?.id ?? editor.getRootBlockId()]
); );
@ -198,17 +210,9 @@ export const TextView = ({
await parentBlock.remove(); await parentBlock.remove();
} }
return true; 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; return true;
} }
); );

View File

@ -1,6 +1,6 @@
import { import {
type BlockEditor,
supportChildren, supportChildren,
type BlockEditor,
} from '@toeverything/components/editor-core'; } from '@toeverything/components/editor-core';
import { Protocol } from '@toeverything/datasource/db-service'; import { Protocol } from '@toeverything/datasource/db-service';
import { AsyncBlock } from '@toeverything/framework/virgo'; 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) { if (editor.getRootBlockId() === block.id) {
return false; return false;
} }

View File

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

View File

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

View File

@ -9,10 +9,10 @@ import {
BlockDecoration, BlockDecoration,
MapOperation, MapOperation,
} from '@toeverything/datasource/jwt'; } from '@toeverything/datasource/jwt';
import { cloneDeep } from '@toeverything/utils';
import type { EventData } from '../block'; import type { EventData } from '../block';
import { AsyncBlock } from '../block'; import { AsyncBlock } from '../block';
import type { Editor } from '../editor'; import type { Editor } from '../editor';
import { cloneDeep } from '@toeverything/utils';
import { SelectBlock } from '../selection'; import { SelectBlock } from '../selection';
export interface CreateView { export interface CreateView {
@ -114,7 +114,21 @@ export abstract class BaseView {
// Whether the component is empty // Whether the component is empty
isEmpty(block: AsyncBlock): boolean { isEmpty(block: AsyncBlock): boolean {
const text = block.getProperty('text'); 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 { getSelProperties(block: AsyncBlock, selectInfo: any): DefaultColumnsValue {

View File

@ -1,15 +1,15 @@
import { HookType, BlockDropPlacement } from '@toeverything/framework/virgo'; import { BlockDropPlacement, HookType } 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 { domToRect, last, Point } from '@toeverything/utils'; 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; const DRAG_THROTTLE_DELAY = 60;
export class LeftMenuPlugin extends BasePlugin { export class LeftMenuPlugin extends BasePlugin {
private _mousedown?: boolean; private _mousedown?: boolean;
@ -111,6 +111,10 @@ export class LeftMenuPlugin extends BasePlugin {
block.dom, block.dom,
block.id block.id
); );
if (!targetBlock.dom) {
console.warn('Can not find dom bind with block', targetBlock);
return;
}
this._lineInfo.next({ this._lineInfo.next({
direction, direction,
blockInfo: { blockInfo: {

View File

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

View File

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